<template>
  <div class="mainDiv">
    <div class="componentDiv">
      <div class="component-group" id="sort_1">
        <ol data-tag="rect"><div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
          <rect x="0" y="0" width="20" height="20" r="0" rx="0" ry="0" fill="none" stroke="#000" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></rect>
        </svg><span style="padding-left: 5px;">矩形</span></div></ol>
        <ol data-tag="circle"><div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
          <circle cx="10" cy="10" r="10" fill="none" stroke="#000" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></circle>
        </svg><span style="padding-left: 5px;">圆形</span></div></ol>
        <ol data-tag="ellipse"><div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
          <ellipse cx="10" cy="10" rx="10" ry="7" fill="none" stroke="#000" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></ellipse>
        </svg><span style="padding-left: 5px;">椭圆</span></div></ol>
        <ol data-tag="triangle"><div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
          <path fill="none" stroke="#000000" d="M0,20L10,0L20,20Z" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path>
        </svg><span style="padding-left: 5px;">三角</span></div></ol>
        <ol data-tag="line"><div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
          <path fill="none" stroke="#000000" d="M0,10L20,10" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path>
        </svg><span style="padding-left: 5px;">横线</span></div></ol>
        <ol data-tag="vline"><div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
          <path fill="none" stroke="#000000" d="M10,0L10,20" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path>
        </svg><span style="padding-left: 5px;">竖线</span></div></ol>
        <ol data-tag="image"><div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
          <image x="0" y="0" width="20" height="20" preserveAspectRatio="none" xlink:href="../../../assets/logo.png" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></image>
        </svg><span style="padding-left: 5px;">图片</span></div></ol>
        <ol data-tag="text"><div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
          <text x="3" y="18" text-anchor="start" font="10px &quot;Arial&quot;" stroke="#000000" fill="#000000" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: start; font: 20px Arial; stroke-width: 2;" stroke-width="2" font-size="20px"><tspan style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);">T</tspan></text>
        </svg><span style="padding-left: 5px;">文本</span></div></ol>
        <ol data-tag="bar"><div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
          <text x="3" y="18" text-anchor="start" font="10px &quot;Arial&quot;" stroke="#000000" fill="#000000" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: start; font: 20px Arial; stroke-width: 2;" stroke-width="2" font-size="20px"><tspan style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);">T</tspan></text>
        </svg><span style="padding-left: 5px;">柱状图</span></div></ol>
        <ol v-for="item in diagramList" :data-tag="item.id"><div class="icon">
          <el-avatar shape="square" :size="20" :src="item.img" />
          <span style="padding-left: 5px;">{{ item.modelName }}</span></div>
        </ol>
      </div>
    </div>
    <div class="diagramDiv" id="diagramDiv">
    </div>
    <div class="btnDiv">
      <el-button type="primary" @click="copy" style="float:left;">复制(ctrl+c)</el-button>
      <el-button type="primary" @click="paste" style="float:left;">粘贴(ctrl+v)</el-button>
      <el-button type="primary" @click="toBack" style="float:left;">置底</el-button>
      <el-button type="primary" @click="toFront" style="float:left;">置顶</el-button>
      <el-button type="primary" @click="deleteObj" style="float:left;">删除(delete)</el-button>
      <el-button type="primary" @click="clear" style="float:left;">清空</el-button>
      <el-button type="primary" @click="saveDialogVisible = true" style="float:left;">保存</el-button>
      <el-button type="primary" @click="exportSvg" style="float:left;">导出svg</el-button>
      <el-button type="primary" @click="exportPng" style="float:left;">导出图片</el-button>
    </div>
    <div class="property" v-show="showProperty">
      <el-form :model="propertyForm" label-width="80" style="padding: 5px;max-width:240px;">
        <el-form-item label="宽度">
          <el-input-number v-model="propertyForm.width" :min="1" :max="500" @change="handleWidth" />
        </el-form-item>
        <el-form-item label="高度">
          <el-input-number v-model="propertyForm.height" :min="1" :max="500" @change="handleHeight" />
        </el-form-item>
        <el-form-item label="半径">
          <el-input-number v-model="propertyForm.radius" :min="1" :max="500" @change="handleRadius" />
        </el-form-item>
        <el-form-item label="旋转角度">
          <el-input-number v-model="propertyForm.rotate" @change="handleRotate" />
        </el-form-item>
        <!-- <el-form-item label="椭圆宽">
          <el-input-number v-model="propertyForm.radiusX" :min="1" :max="500" @change="handleRadiusX" />
        </el-form-item>
        <el-form-item label="椭圆高">
          <el-input-number v-model="propertyForm.radiusY" :min="1" :max="500" @change="handleRadiusY" />
        </el-form-item> -->
        <el-form-item label="线宽">
          <el-input-number v-model="propertyForm.strokeWidth" :min="1" :max="50" @change="handleStrokeWidth" />
        </el-form-item>
        <el-form-item label="线颜色">
          <el-color-picker v-model="propertyForm.stroke" @change="handleStroke" />
        </el-form-item>
        <el-form-item label="填充">
          <el-color-picker v-model="propertyForm.fill" @change="handleFill" />
        </el-form-item>
        <el-form-item label="图片">
          <el-upload
            class="image-select"
            action="/api/upload/uploadFile"
            :show-file-list="false"
            :on-success="handleImgSuccess"
            :before-upload="beforeImgUpload"
            accept="image/*"
          >
            <img v-if="propertyForm.img" :src="propertyForm.img" class="image" />
            <el-icon v-else class="image-select-icon"><Plus /></el-icon>
          </el-upload>
        </el-form-item>
        <el-form-item label="文字内容">
          <el-input v-model="propertyForm.text" @change="handleText" />
        </el-form-item>
        <el-form-item label="文字绑定">
          <el-button type="primary" @click="bindDataSource">绑定数据源</el-button>
        </el-form-item>
        <el-form-item label="字体大小">
          <el-input-number v-model="propertyForm.fontSize" :min="1" :max="80" @change="handleFontSize" />
        </el-form-item>
        <el-form-item label="x轴">
          <el-input-number v-model="propertyForm.x" @change="handlePositionX" />
        </el-form-item>
        <el-form-item label="y轴">
          <el-input-number v-model="propertyForm.y" @change="handlePositionY" />
        </el-form-item>
        <el-form-item label="x轴数据源">
          <el-button type="primary" @click="bindXAxis">绑定数据源</el-button>
        </el-form-item>
        <el-form-item label="y轴数据源">
          <el-button type="primary" @click="bindYAxis">绑定数据源</el-button>
        </el-form-item>
      </el-form>
    </div>
    <p class="slide">
      <el-button :icon="activeIcon" @click="showPropertyDiv" class="slide-btn"></el-button>
    </p>
    <el-dialog v-model="saveDialogVisible" title="保存" width="350">
      <el-form :model="form">
        <el-form-item label="图表名称" label-width="100">
          <el-input v-model="diagramForm.modelName" autocomplete="off" />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="saveDialogVisible = false">取消</el-button>
          <el-button type="primary" @click="saveDiagram">
            确定
          </el-button>
        </div>
      </template>
    </el-dialog>
    <el-dialog v-model="dataSourceVisible" title="数据源" width="450">
      <el-form :model="form">
        <el-form-item label="数据源" label-width="100">
          <el-select v-model="dataSourceForm.dataSource" placeholder="请选择数据源" @change="handleDataSource">
            <el-option
            v-for="item in dataSourceList"
            :key="item.tableName"
            :value="item.tableName"
            :label="item.formName"/>
          </el-select>
        </el-form-item>
        <el-form-item label="数据字段" label-width="100">
          <el-radio-group v-model="dataSourceForm.column">
            <el-radio v-for="item in tableColumnList" :value="item.columnName">{{item.description}}</el-radio>
          </el-radio-group>
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="dataSourceVisible = false">取消</el-button>
          <el-button type="primary" @click="selectDataSource">
            确定
          </el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
defineOptions({
  name: "Diagram",
  inheritAttrs: false,
});
import router from "@/router";
import DesdiagramAPI, { DesdiagramPageVO, DesdiagramData } from "@/api/desdiagram";
import DesformAPI, { FormPageVO, FormPageQuery, DesFormColumn } from "@/api/desform";
import Sortable from 'sortablejs';
const route = useRoute();

const diagramList = ref([]);

let paper = null;
let mainArr = [];
let resizeSet = null;
let currentObj = null; // 当前组件
let objCenterX = 0;
let objCenterY = 0;
let copyObj = null; // 复制的组件

let undos = []; // 已执行命令集合
let redos = []; // 待执行命令集合

// 定义缩放旋转按钮
let nResize, eResize, sResize, wResize, neResize, nwResize, seResize, swResize, rotateBtn;
// paper屏幕边距
const leftMargin = 410;
const topMargin = 50
const objMaxsize = 1000; // 组件尺寸最大值

// 图表对象
const diagramForm = reactive({
  id: 0,
  modelName: "",
  elements: "",
  img: ""
})

// 属性相关
const showProperty = ref(false);
const propertyForm = reactive({
  width: 100,
  height: 100,
  radius: 50,
  rotate: 0,
  radiusX: 50,
  radiusY: 25,
  strokeWidth: 1,
  stroke: "#666",
  fill: "white",
  img: "",
  text: "这里是文字",
  fontSize: 18,
  x: 0,
  y: 0,
})
function handleWidth(value){
  if (currentObj && currentObj.getBBox().width != 0){
    objCenterX = currentObj.getBBox().x + currentObj.getBBox().width / 2;
    objCenterY = currentObj.getBBox().y + currentObj.getBBox().height / 2;
    undos.push({ command: "ResizeObjectCommand", obj: currentObj, dWidth: value / currentObj.getBBox().width, dHeight: 1 });
    currentObj.scale(value / currentObj.getBBox().width, 1, objCenterX, objCenterY).resetScale();
  }
}
function handleHeight(value){
  if (currentObj && currentObj.getBBox().height != 0){
    objCenterX = currentObj.getBBox().x + currentObj.getBBox().width / 2;
    objCenterY = currentObj.getBBox().y + currentObj.getBBox().height / 2;
    undos.push({ command: "ResizeObjectCommand", obj: currentObj, dWidth: 1, dHeight: value / currentObj.getBBox().height });
    currentObj.scale(1, value / currentObj.getBBox().height, objCenterX, objCenterY).resetScale();
  }
}
function handleRadius(value){
  if (currentObj){
    let r = currentObj.attr("r");
    undos.push({ command: "ResizeObjectCommand", obj: currentObj, dWidth: value / r, dHeight: value / r });
    currentObj.attr("r", value);
  }
}
function handleRotate(value){
  if (currentObj){
    let startRotate = currentObj.attrs["rotate"] ? currentObj.attrs["rotate"] : 0;
    undos.push({ command: "RotateObjectCommand", obj: currentObj, startRotate: startRotate, rotate: value - startRotate });
    currentObj.rotate(value, objCenterX, objCenterY);
    currentObj.attrs["rotate"] = value;
  }
}
function handleRadiusX(value){
  if (currentObj){
    currentObj.attr("rx", value)
  }
}
function handleRadiusY(value){
  if (currentObj){
    currentObj.attr("ry", value)
  }
}
function handleStrokeWidth(value){
  if (currentObj){
    let startWidth = currentObj.attr("stroke-width");
    undos.push({ command: "StrokeWidthCommand", obj: currentObj, startWidth: startWidth, width: value });
    currentObj.attr("stroke-width", value);
  }
}
function handleStroke(value){
  if (currentObj){
    let startStroke = currentObj.attr("stroke");
    undos.push({ command: "StrokeCommand", obj: currentObj, startStroke: startStroke, stroke: value });
    currentObj.attr("stroke", value);
  }
}
function handleFill(value){
  if (currentObj){
    let startFill = currentObj.attr("fill");
    undos.push({ command: "FillCommand", obj: currentObj, startFill: startFill, fill: value });
    currentObj.attr("fill", value);
  }
}
function handleText(value){
  if (currentObj){
    let startText = currentObj.attr("text");
    undos.push({ command: "TextCommand", obj: currentObj, startText: startText, text: value });
    currentObj.attr("text", value)
  }
}
function bindDataSource(){
  if (currentObj && currentObj.type == "text"){
    dataSourceForm.dataSource = currentObj.attrs["dataSource"];
    dataSourceForm.column = currentObj.attrs["column"];
    dataSourceVisible.value = true;
  }
  else{
    ElMessage.warning("请选择文本组件");
  }
}
function handleFontSize(value){
  if (currentObj){
    let startFontSize = currentObj.attr("font-size");
    undos.push({ command: "FontSizeCommand", obj: currentObj, startFontSize: startFontSize, fontSize: value });
    currentObj.attr("font-size", value)
  }
}
function handlePositionX(value){
  if (currentObj){
    initResizeFlowMove();
    let sourceX = currentObj.getBBox().x;
    currentObj.translate(value - sourceX, 0);
    resizeFlowMove(value - sourceX, 0);
    undos.push({ command: "MoveObjectCommand", obj: currentObj, dx: value - sourceX, dy: 0 });
  }
}
function handlePositionY(value){
  if (currentObj){
    initResizeFlowMove();
    let sourceY = currentObj.getBBox().y;
    currentObj.translate(0, value - sourceY);
    resizeFlowMove(0, value - sourceY);
    undos.push({ command: "MoveObjectCommand", obj: currentObj, dx: 0, dy: value - sourceY });
  }
}
const handleImgSuccess: UploadProps['onSuccess'] = (
  response,
  uploadFile
) => {
  propertyForm.img = response.data;
  if (currentObj){
    let startSrc = currentObj.attr("src");
    undos.push({ command: "ImageCommand", obj: currentObj, startSrc: startSrc, src: response.data });
    currentObj.attr("src", response.data);
  }
}
const beforeImgUpload: UploadProps['beforeUpload'] = (rawFile) => {
  if (rawFile.size / 1024 / 1024 > 10) {
    ElMessage.error('图片大小不能超过10MB!')
    return false
  }
  return true
}

// 数据源相关
const dataSourceList = ref([]);
const dataSourceVisible = ref(false);
const dataSourceForm = reactive({
  dataSource: "",
  column: "",
})
const tableColumnList = ref<DesFormColumn[]>();
/** 查询数据源 */
const dataSourceQueryParams = reactive<FormPageQuery>({
  page: 1,
  size: 500,
});
function handleQueryDataSource() {
  DesformAPI.getPage(dataSourceQueryParams)
    .then(({data}) => {
      dataSourceList.value = data.list;
    })
}
function handleDataSource(value){
  DesformAPI.getTableColumns(value)
    .then(({data}) => {
      tableColumnList.value = data;
    })
}
function selectDataSource(){
  if (currentObj && currentObj.type == "text"){
    currentObj.attrs["dataSource"] = dataSourceForm.dataSource;
    currentObj.attrs["column"] = dataSourceForm.column;
    dataSourceVisible.value = false;
    ElMessage.success("绑定成功");
  }
}
watch(() => dataSourceForm.dataSource, (newVal, oldVal) => {
    handleDataSource(newVal);
  }, {
    deep: true, // 开启深度监听
});

// 初始化
onMounted(() => {
  const diagram = document.getElementById("diagramDiv");
  const getById = document.getElementById("sort_1");
  new Sortable(getById, {
      group: {
          name: "formDesign",
          pull: 'clone',
          put: false,
      },
      sort: false,
      animation: 150,
      onChoose: function (evt: any) { },  // 拖动前显示
      onAdd: function (evt: any) { 
      },     // 添加到这里
      onEnd: function (evt: any) { },     // 拖动结束
  });

  let width = diagram.clientWidth;
  let height = diagram.clientHeight;
  paper = new Raphael("diagramDiv", width, height);
  paper.canvas.id = "paper";

  resizeSet = paper.set();
  // 定义缩放旋转按钮
  nResize = drawScaleBtn(paper, "n");
  eResize = drawScaleBtn(paper, "e");
  sResize = drawScaleBtn(paper, "s");
  wResize = drawScaleBtn(paper, "w");
  neResize = drawScaleBtn(paper, "ne");
  nwResize = drawScaleBtn(paper, "nw");
  seResize = drawScaleBtn(paper, "se");
  swResize = drawScaleBtn(paper, "sw");
  resizeSet.push(nResize, eResize, sResize, wResize, neResize, nwResize, seResize, swResize);
  rotateBtn = drawRotateBtn(paper);

  // paper绘制图形
  const elem = document.getElementById("paper");
  new Sortable(elem, {
    group: {
        name: "formDesign",
    },
    sort: false,
    animation: 150,
    filter: function (evt: any, item: any) {
        return false;
    },
    onAdd: function (evt: { newIndex: any; item: any; }) {
      for (let i = 0; i < elem.children.length; i++) {
        if (elem.children[i].tagName === "OL"){
          elem.removeChild(elem.children[i]);
        }
      }
      switch (evt.item.dataset.tag){
        case "rect":
          currentObj = drawRect(paper, evt.originalEvent.clientX - leftMargin, evt.originalEvent.clientY - topMargin, 
            100, 100, 1, "white", "#666");
          objCenterX = currentObj.getBBox().x + 50;
          objCenterY = currentObj.getBBox().y + 50;
          translateAndShowResizeBtn(true, true, true, true, true, true, true, true, true);
          // 属性初始化
          propertyForm.width = 100;
          propertyForm.height = 100;
          propertyForm.strokeWidth = 1;
          propertyForm.stroke = "#666";
          propertyForm.fill = "#ffffff";
          propertyForm.x = currentObj.getBBox().x;
          propertyForm.y = currentObj.getBBox().y;
        break;
        case "circle":
          currentObj = drawCircle(paper, evt.originalEvent.clientX - leftMargin, evt.originalEvent.clientY - topMargin, 
            50, 1, "white", "#666");
          objCenterX = currentObj.getBBox().x + 50;
          objCenterY = currentObj.getBBox().y + 50;
          translateAndShowResizeBtn(false, false, false, false, true, true, true, true, false);
          // 属性初始化
          propertyForm.radius = 50;
          propertyForm.strokeWidth = 1;
          propertyForm.stroke = "#666";
          propertyForm.fill = "#ffffff";
          propertyForm.x = currentObj.getBBox().x;
          propertyForm.y = currentObj.getBBox().y;
        break;
        case "ellipse":
          currentObj = drawEllipse(paper, evt.originalEvent.clientX - leftMargin, evt.originalEvent.clientY - topMargin, 
            50, 25, 1, "white", "#666");
          objCenterX = currentObj.getBBox().x + 50;
          objCenterY = currentObj.getBBox().y + 25;
          translateAndShowResizeBtn(true, true, true, true, true, true, true, true, true);
          // 属性初始化
          propertyForm.width = 100;
          propertyForm.height = 50;
          propertyForm.strokeWidth = 1;
          propertyForm.stroke = "#666";
          propertyForm.fill = "#ffffff";
          propertyForm.x = currentObj.getBBox().x;
          propertyForm.y = currentObj.getBBox().y;
        break;
        case "triangle":
          currentObj = drawTriangle(paper, evt.originalEvent.clientX - leftMargin, evt.originalEvent.clientY - topMargin, 
            100, 100, 1, "white", "#666");
          objCenterX = currentObj.getBBox().x + 50;
          objCenterY = currentObj.getBBox().y + 50;
          translateAndShowResizeBtn(true, true, true, true, true, true, true, true, true);
          // 属性初始化
          let trianglePath = currentObj.attr("path");
          propertyForm.width = trianglePath[2][1] - trianglePath[0][1];
          propertyForm.height = trianglePath[0][2] - trianglePath[1][2];
          propertyForm.strokeWidth = 1;
          propertyForm.stroke = "#666";
          propertyForm.fill = "#ffffff";
          propertyForm.x = currentObj.getBBox().x;
          propertyForm.y = currentObj.getBBox().y;
        break;
        case "line":
          currentObj = drawLine(paper, evt.originalEvent.clientX - leftMargin, evt.originalEvent.clientY - topMargin, 
            100, 2, "#666");
          objCenterX = currentObj.getBBox().x + 50;
          objCenterY = currentObj.getBBox().y;
          translateAndShowResizeBtn(false, true, false, true, false, false, false, false, true);
          // 属性初始化
          let linePath = currentObj.attr("path");
          propertyForm.width = linePath[1][1] - linePath[0][1];
          propertyForm.strokeWidth = 2;
          propertyForm.stroke = "#666";
          propertyForm.x = currentObj.getBBox().x;
          propertyForm.y = currentObj.getBBox().y;
        break;
        case "vline":
          currentObj = drawVerticalLine(paper, evt.originalEvent.clientX - leftMargin, evt.originalEvent.clientY - topMargin, 
            100, 2, "#666");
          objCenterX = currentObj.getBBox().x;
          objCenterY = currentObj.getBBox().y + 50;
          translateAndShowResizeBtn(true, false, true, false, false, false, false, false, true);
          // 属性初始化
          let vlinePath = currentObj.attr("path");
          propertyForm.height = vlinePath[1][2] - vlinePath[0][2];
          propertyForm.strokeWidth = 2;
          propertyForm.stroke = "#666";
          propertyForm.x = currentObj.getBBox().x;
          propertyForm.y = currentObj.getBBox().y;
        break;
        case "image":
          currentObj = drawImage(paper, evt.originalEvent.clientX - leftMargin, evt.originalEvent.clientY - topMargin, 
            "/src/assets/logo.png", 50, 50, 1);
          objCenterX = currentObj.getBBox().x + 25;
          objCenterY = currentObj.getBBox().y + 25;
          translateAndShowResizeBtn(false, false, false, false, true, true, true, true, true);
          // 属性初始化
          propertyForm.width = 50;
          propertyForm.height = 50;
          propertyForm.strokeWidth = 1;
          propertyForm.img = "/src/assets/logo.png";
          propertyForm.x = currentObj.getBBox().x;
          propertyForm.y = currentObj.getBBox().y;
        break;
        case "text":
          currentObj = drawText(paper, evt.originalEvent.clientX - leftMargin, evt.originalEvent.clientY - topMargin, 
            "这里是文字", 18, 1, "#666", "#000");
          objCenterX = currentObj.getBBox().x + currentObj.getBBox().width / 2 ;
          objCenterY = currentObj.getBBox().y;
          translateAndShowResizeBtn(false, false, false, false, false, false, false, false, true);
          // 属性初始化
          propertyForm.text = "这里是文字";
          propertyForm.fontSize = 18;
          propertyForm.strokeWidth = 1;
          propertyForm.stroke = "#000";
          propertyForm.fill = "#666";
          propertyForm.x = currentObj.getBBox().x;
          propertyForm.y = currentObj.getBBox().y;
        break;
        case "bar":
          currentObj = drawBar(paper, 16, 2, "#fff", "#000");
          let x = elem.getBBox().x + elem.getBBox().width / 2;
          let y = elem.getBBox().y + elem.getBBox().height / 2;
          currentObj.translate(evt.originalEvent.clientX - leftMargin - x, evt.originalEvent.clientY - topMargin - y);
          objCenterX = currentObj.getBBox().x + currentObj.getBBox().width / 2;
          objCenterY = currentObj.getBBox().y + currentObj.getBBox().height / 2;
          translateAndShowResizeBtn(false, false, false, false, true, true, true, true, false);
          // 属性初始化
          propertyForm.x = currentObj.getBBox().x;
          propertyForm.y = currentObj.getBBox().y;
        break;
        default:
          let currentDiagram = null;
          for(let i = 0; i < diagramList.value.length; i++){
            let diagram = diagramList.value[i];
            if (diagram.id == evt.item.dataset.tag){
              currentDiagram = diagram;
            }
          }
          if (currentDiagram){
            let elements = JSON.parse(currentDiagram.elements);
            currentObj = drawUserObj(elements);
            let x = elem.getBBox().x + elem.getBBox().width / 2;
            let y = elem.getBBox().y + elem.getBBox().height / 2;
            currentObj.translate(evt.originalEvent.clientX - leftMargin - x, evt.originalEvent.clientY - topMargin - y);
            objCenterX = currentObj.getBBox().x + currentObj.getBBox().width / 2;
            objCenterY = currentObj.getBBox().y + currentObj.getBBox().height / 2;
            translateAndShowResizeBtn(false, false, false, false, true, true, true, true, false);

            propertyForm.x = currentObj.getBBox().x;
            propertyForm.y = currentObj.getBBox().y;
          }
        break;
      }
      mainArr.push(currentObj);
      showProperty.value = true;
      activeIcon.value = "ArrowRightBold";
      undos.push({ command: "AddObjectCommand", obj: currentObj });
    },
    onUpdate: function (evt: { to: { id: any; }; newIndex: string | number; oldIndex: string | number; }) {
    },
    onEnd: function (evt: any) { 
    }
  });

  if (route.query.id){
    diagramForm.id = route.query.id;
    DesdiagramAPI.getById(route.query.id).then(({data}) => {
      if (data){
        diagramForm.modelName = data.modelName;
        diagramForm.elements = data.elements;
        diagramForm.img = data.img;
        let eleJson = JSON.parse(data.elements);
        for(let i = 0; i < eleJson.length; i++){
          let element = eleJson[i];
          addObj(element);
        }
      }
    })
  }

  // 获取用户创建的图表
  DesdiagramAPI.getByCreator()
    .then(({data}) => {
      diagramList.value = data;
    })

  // 获取数据源
  handleQueryDataSource();

  //Delete按键删除事件
  document.addEventListener('keydown', function(event) {
    switch(event.keyCode || event.key) {
      case 46: // 删除
      case 'Delete':
        deleteObj();
        break;
      case 37: // 左键
      case 'ArrowLeft':
        if (currentObj){
          currentObj.translate(-1, 0);
          resizeFlowKeyMove(-1, 0);
          propertyForm.x = currentObj.getBBox().x;
          propertyForm.y = currentObj.getBBox().y;
          undos.push({ command: "MoveObjectCommand", obj: currentObj, dx: -1, dy: 0 });
        }
        break;
      case 38: // 上键
      case 'ArrowUp':
        if (currentObj){
          currentObj.translate(0, -1);
          resizeFlowKeyMove(0, -1);
          propertyForm.x = currentObj.getBBox().x;
          propertyForm.y = currentObj.getBBox().y;
          undos.push({ command: "MoveObjectCommand", obj: currentObj, dx: 0, dy: -1 });
        }
        break;
      case 39: // 右键
      case 'ArrowRight':
        if (currentObj){
          currentObj.translate(1, 0);
          resizeFlowKeyMove(1, 0);
          propertyForm.x = currentObj.getBBox().x;
          propertyForm.y = currentObj.getBBox().y;
          undos.push({ command: "MoveObjectCommand", obj: currentObj, dx: 1, dy: 0 });
        }
        break;
      case 40: // 下键
      case 'ArrowDown':
        if (currentObj){
          currentObj.translate(0, 1);
          resizeFlowKeyMove(0, 1);
          propertyForm.x = currentObj.getBBox().x;
          propertyForm.y = currentObj.getBBox().y;
          undos.push({ command: "MoveObjectCommand", obj: currentObj, dx: 0, dy: 1 });
        }
        break;
      default:
          break;
    }

    if (event.key === "z" && event.ctrlKey){
      undo();
    }
    if (event.key === "y" && event.ctrlKey){
      redo();
    }
  });

  // 监听剪贴板的复制事件
  document.addEventListener('copy', function(event) {
    copy();
    event.preventDefault(); // 阻止默认的复制行为
  });

  // 监听粘贴事件
  document.addEventListener('paste', function(event) {
    paste();
    event.preventDefault(); // 阻止默认的粘贴行为
  });

  // 为window添加鼠标滚轮事件监听
  document.addEventListener('wheel', function(event) {
    // event.deltaY 大于0表示向下滚动，小于0表示向上滚动
    // console.log('滚动方向：' + (event.deltaY > 0 ? '向下' : '向上') + '，滚动距离：' + Math.abs(event.deltaY) + 'px');
    if (currentObj){
      let width = currentObj.getBBox().width;
      let height = currentObj.getBBox().height;
      objCenterX = currentObj.getBBox().x + currentObj.getBBox().width / 2;
      objCenterY = currentObj.getBBox().y + currentObj.getBBox().height / 2;
      if (width == 0){ // 竖线
        if (event.deltaY > 0 ){ // 缩小
          if (height > 2) {
            currentObj.scale(1, (height - 2) / height, objCenterX, objCenterY).resetScale();
            undos.push({ command: "ResizeObjectCommand", obj: currentObj, dWidth: 1, dHeight: (height - 2) / height });
          }
        }else{ // 放大
          if (width < objMaxsize && height < objMaxsize) {
            currentObj.scale(1, (height + 2) / height, objCenterX, objCenterY).resetScale();
            undos.push({ command: "ResizeObjectCommand", obj: currentObj, dWidth: 1, dHeight: (height + 2) / height });
          }
        }
      }
      else if (currentObj.type == "text"){ // 文本
        if (event.deltaY > 0 ){ // 缩小
          if (currentObj.attr("font-size") > 2) {
            currentObj.attr("font-size", currentObj.attr("font-size") - 1);
            undos.push({ command: "ResizeTextCommand", obj: currentObj, dsize: -1 });
          }
        }else{ // 放大
          if (currentObj.attr("font-size") < 80) {
            currentObj.attr("font-size", currentObj.attr("font-size") + 1);
            undos.push({ command: "ResizeTextCommand", obj: currentObj, dsize: 1 });
          }
        }
      }
      else if (currentObj.type == "set"){ // 集合
        let childRotate = [];
        for(let i = 0; i < currentObj.length; i++){
          let elem = currentObj[i];
          childRotate[i] = elem.attrs["rotate"];
          if (childRotate[i]){
            elem.rotate(0, elem.getBBox().x + elem.getBBox().width / 2, elem.getBBox().y + elem.getBBox().height / 2);
          }
        }
        if (event.deltaY > 0 ){ // 缩小
          if (width > 2) {
            currentObj.scale((width - 2) / width, (width - 2) / width, objCenterX, objCenterY).resetScale();
            undos.push({ command: "ResizeObjectCommand", obj: currentObj, dWidth: (width - 2) / width, dHeight: (width - 2) / width });
          }
        }else{ // 放大
          if (width < objMaxsize && height < objMaxsize) {
            currentObj.scale((width + 2) / width, (width + 2) / width, objCenterX, objCenterY).resetScale();
            undos.push({ command: "ResizeObjectCommand", obj: currentObj, dWidth: (width + 2) / width, dHeight: (width + 2) / width });
          }
        }
        for(let i = 0; i < currentObj.length; i++){
          let elem = currentObj[i];
          if (childRotate[i]){
            elem.rotate(childRotate[i], elem.getBBox().x + elem.getBBox().width / 2, elem.getBBox().y + elem.getBBox().height / 2);
          }
        }
      }
      else{
        if (event.deltaY > 0 ){ // 缩小
          if (width > 2) {
            currentObj.scale((width - 2) / width, (width - 2) / width, objCenterX, objCenterY).resetScale();
            undos.push({ command: "ResizeObjectCommand", obj: currentObj, dWidth: (width - 2) / width, dHeight: (width - 2) / width });
          }
        }else{ // 放大
          if (width < objMaxsize && height < objMaxsize) {
            currentObj.scale((width + 2) / width, (width + 2) / width, objCenterX, objCenterY).resetScale();
            undos.push({ command: "ResizeObjectCommand", obj: currentObj, dWidth: (width + 2) / width, dHeight: (width + 2) / width });
          }
        }
      }
      setProperty();
    }
  });
});

/*
  * 设置组件属性值
*/
function setProperty(){
  switch (currentObj.type){
    case "rect":
    case "image":
      propertyForm.width = currentObj.attr("width");
      propertyForm.height = currentObj.attr("height");
    break;
    case "circle":
      propertyForm.radius = currentObj.attr("r");
    break;
    case "ellipse":
      propertyForm.width = currentObj.getBBox().width;
      propertyForm.height = currentObj.getBBox().height;
    break;
    case "path":
      let path = currentObj.attr("path");
      if (path.length == 2){ // 直线
        if (path[1][2] == path[0][2]){ // 横线
          let width = path[1][1] - path[0][1];
          propertyForm.width = width;
        }
        else{ // 竖线
          let height = path[1][2] - path[0][2];
          propertyForm.height = height;
        }
      }
      else { // 三角
        let width = path[2][1] - path[0][1];
        let height = path[0][2] - path[1][2];
        propertyForm.width = width;
        propertyForm.height = height;
      }
    break;
    case "text":
      propertyForm.fontSize = currentObj.attr("font-size");;
    break;
  }
}

/*
  * 复制
*/
function copy(){
  copyObj = currentObj;
}

/*
  * 粘贴
*/
function paste(){
  // 处理粘贴的内容
  if (copyObj != null){
    switch (copyObj.type){
      case "rect":
        currentObj = drawRect(paper, copyObj.attrs["x"], copyObj.attrs["y"], copyObj.attrs["width"], copyObj.attrs["height"], 
        copyObj.attrs["stroke-width"], copyObj.attrs["fill"], copyObj.attrs["stroke"], copyObj.attrs["rotate"]);
        currentObj.translate(100, 100);
        objCenterX = currentObj.getBBox().x + currentObj.getBBox().width / 2;
        objCenterY = currentObj.getBBox().y + currentObj.getBBox().height / 2;
        translateAndShowResizeBtn(true, true, true, true, true, true, true, true, true);
        // 属性初始化
        propertyForm.width = copyObj.attrs["width"];
        propertyForm.height = copyObj.attrs["height"];
        propertyForm.strokeWidth = copyObj.attrs["stroke-width"];
        propertyForm.stroke = copyObj.attrs["stroke"];
        propertyForm.fill = copyObj.attrs["fill"];
        propertyForm.x = currentObj.getBBox().x;
        propertyForm.y = currentObj.getBBox().y;
        mainArr.push(currentObj);
        undos.push({ command: "CopyObjectCommand", obj: currentObj });
      break;
      case "circle":
        currentObj = drawCircle(paper, copyObj.attrs["cx"], copyObj.attrs["cy"], copyObj.attrs["r"], 
          copyObj.attrs["stroke-width"], copyObj.attrs["fill"], copyObj.attrs["stroke"]);
        currentObj.translate(100, 100);
        objCenterX = currentObj.getBBox().x + currentObj.getBBox().width / 2;
        objCenterY = currentObj.getBBox().y + currentObj.getBBox().height / 2;
        translateAndShowResizeBtn(false, false, false, false, true, true, true, true, false);
        // 属性初始化
        propertyForm.radius = copyObj.attrs["r"];
        propertyForm.strokeWidth = copyObj.attrs["stroke-width"];
        propertyForm.stroke = copyObj.attrs["stroke"];
        propertyForm.fill = copyObj.attrs["fill"];
        propertyForm.x = currentObj.getBBox().x;
        propertyForm.y = currentObj.getBBox().y;
        mainArr.push(currentObj);
        undos.push({ command: "CopyObjectCommand", obj: currentObj, copyObj: copyObj });
      break;
      case "ellipse":
        currentObj = drawEllipse(paper, copyObj.attrs["cx"], copyObj.attrs["cy"], copyObj.attrs["rx"], copyObj.attrs["ry"], 
          copyObj.attrs["stroke-width"], copyObj.attrs["fill"], copyObj.attrs["stroke"], copyObj.attrs["rotate"]);
        currentObj.translate(100, 100);
        objCenterX = currentObj.getBBox().x + currentObj.getBBox().width / 2;
        objCenterY = currentObj.getBBox().y + currentObj.getBBox().height / 2;
        translateAndShowResizeBtn(true, true, true, true, true, true, true, true, true);
        // 属性初始化
        propertyForm.radiusX = copyObj.attrs["rx"];
        propertyForm.radiusY = copyObj.attrs["ry"];
        propertyForm.strokeWidth = copyObj.attrs["stroke-width"];
        propertyForm.stroke = copyObj.attrs["stroke"];
        propertyForm.fill = copyObj.attrs["fill"];
        propertyForm.x = currentObj.getBBox().x;
        propertyForm.y = currentObj.getBBox().y;
        mainArr.push(currentObj);
        undos.push({ command: "CopyObjectCommand", obj: currentObj });
      break;
      case "path":
        if (copyObj.attrs["path"].length == 2){ // 直线
          let linePath = copyObj.attrs["path"];
          if (linePath[1][2] == linePath[0][2]){ // 横线
            let lineWidth = linePath[1][1] - linePath[0][1];
            let lineX = linePath[0][1] + lineWidth / 2;
            let lineY = linePath[0][2];
            currentObj = drawLine(paper, lineX, lineY, lineWidth, copyObj.attrs["stroke-width"], copyObj.attrs["stroke"], copyObj.attrs["rotate"]);
            currentObj.translate(100, 100);
            objCenterX = currentObj.getBBox().x + currentObj.getBBox().width / 2;
            objCenterY = currentObj.getBBox().y + currentObj.getBBox().height / 2;
            translateAndShowResizeBtn(false, true, false, true, false, false, false, false, true);
          }
          else{
            let lineHeight = linePath[1][2] - linePath[0][2];
            let lineX = linePath[0][1];
            let lineY = linePath[0][2] + lineHeight / 2;
            currentObj = drawVerticalLine(paper, lineX, lineY, lineHeight, copyObj.attrs["stroke-width"], copyObj.attrs["stroke"], copyObj.attrs["rotate"]);
            currentObj.translate(100, 100);
            objCenterX = currentObj.getBBox().x + currentObj.getBBox().width / 2;
            objCenterY = currentObj.getBBox().y + currentObj.getBBox().height / 2;
            translateAndShowResizeBtn(true, false, true, false, false, false, false, false, true);
          }
          // 属性初始化
          propertyForm.strokeWidth = copyObj.attrs["stroke-width"];
          propertyForm.stroke = copyObj.attrs["stroke"];
          propertyForm.x = currentObj.getBBox().x;
          propertyForm.y = currentObj.getBBox().y;
          mainArr.push(currentObj);
          undos.push({ command: "CopyObjectCommand", obj: currentObj });
        }
        else{ // 三角
          let path = copyObj.attrs["path"];
          let width = path[2][1] - path[0][1];
          let height = path[0][2] - path[1][2];
          let x = path[0][1] + width / 2;
          let y = path[0][2] - height / 2;
          currentObj = drawTriangle(paper, x, y, width, height, copyObj.attrs["stroke-width"], copyObj.attrs["fill"], copyObj.attrs["stroke"], copyObj.attrs["rotate"]);
          currentObj.translate(100, 100);
          objCenterX = currentObj.getBBox().x + currentObj.getBBox().width / 2;
          objCenterY = currentObj.getBBox().y + currentObj.getBBox().height / 2;
          translateAndShowResizeBtn(true, true, true, true, true, true, true, true, true);
          // 属性初始化
          propertyForm.strokeWidth = copyObj.attrs["stroke-width"];
          propertyForm.stroke = copyObj.attrs["stroke"];
          propertyForm.fill = copyObj.attrs["fill"];
          propertyForm.x = currentObj.getBBox().x;
          propertyForm.y = currentObj.getBBox().y;
          mainArr.push(currentObj);
          undos.push({ command: "CopyObjectCommand", obj: currentObj });
        }
      break;
      case "image":
        currentObj = drawImage(paper, copyObj.attrs["x"], copyObj.attrs["y"], copyObj.attrs["src"], copyObj.attrs["width"], 
          copyObj.attrs["height"], copyObj.attrs["stroke-width"], copyObj.attrs["rotate"]);
        currentObj.translate(100, 100);
        objCenterX = currentObj.getBBox().x + currentObj.getBBox().width / 2;
        objCenterY = currentObj.getBBox().y + currentObj.getBBox().height / 2;
        translateAndShowResizeBtn(false, false, false, false, true, true, true, true, true);
        // 属性初始化
        propertyForm.width = copyObj.attrs["width"];
        propertyForm.height = copyObj.attrs["height"];
        propertyForm.strokeWidth = copyObj.attrs["stroke-width"];
        propertyForm.img = copyObj.attrs["src"];
        propertyForm.x = currentObj.getBBox().x;
        propertyForm.y = currentObj.getBBox().y;
        mainArr.push(currentObj);
        undos.push({ command: "CopyObjectCommand", obj: currentObj });
      break;
      case "text":
        currentObj = drawText(paper, copyObj.attrs["x"], copyObj.attrs["y"], copyObj.attrs["text"], copyObj.attrs["font-size"], 
          copyObj.attrs["stroke-width"], copyObj.attrs["fill"], copyObj.attrs["stroke"], copyObj.attrs["rotate"],
          copyObj.attrs["dataSource"], copyObj.attrs["column"]);
        currentObj.translate(100, 100);
        objCenterX = currentObj.getBBox().x + currentObj.getBBox().width / 2;
        objCenterY = currentObj.getBBox().y + currentObj.getBBox().height / 2;
        translateAndShowResizeBtn(false, false, false, false, false, false, false, false, true);
        // 属性初始化
        propertyForm.text = copyObj.attrs["text"];
        propertyForm.fontSize = copyObj.attrs["font-size"];
        propertyForm.strokeWidth = copyObj.attrs["stroke-width"];
        propertyForm.stroke = copyObj.attrs["stroke"];
        propertyForm.fill = copyObj.attrs["fill"];
        propertyForm.x = currentObj.getBBox().x;
        propertyForm.y = currentObj.getBBox().y;
        mainArr.push(currentObj);
        undos.push({ command: "CopyObjectCommand", obj: currentObj });
      break;
      case "set":
        currentObj = drawUserObj(copyObj);
        currentObj.translate(100, 100);
        objCenterX = currentObj.getBBox().x + currentObj.getBBox().width / 2;
        objCenterY = currentObj.getBBox().y + currentObj.getBBox().height / 2;
        translateAndShowResizeBtn(false, false, false, false, true, true, true, true, false);
        propertyForm.x = currentObj.getBBox().x;
        propertyForm.y = currentObj.getBBox().y;
        mainArr.push(currentObj);
        undos.push({ command: "CopyObjectCommand", obj: currentObj });
      break;
      default:
      break;
    }
  }
}

/*
  * 撤销
*/
function undo(){
  if (undos.length > 0){
    let cmd = undos.pop();
    switch(cmd.command){
      case "CopyObjectCommand":
        cmd.obj.hide();
        if (currentObj == cmd.obj){
          currentObj = null;
          rotateBtn.hide();
          resizeSet.hide();
        }
      break;
      case "DeleteObjectCommand":
        cmd.obj.show();
      break;
      case "AddObjectCommand":
        cmd.obj.hide();
      break;
      case "MoveObjectCommand":
        cmd.obj.translate(-cmd.dx, -cmd.dy);
        if (currentObj == cmd.obj){
          currentObj = null;
          rotateBtn.hide();
          resizeSet.hide();
        }
      break;
      case "ResizeObjectCommand":
        let width = cmd.obj.getBBox().width;
        let height = cmd.obj.getBBox().height;
        if (width == 0){
          cmd.obj.scale(1, 1 / cmd.dHeight).resetScale();
        }
        else if (height == 0){
          cmd.obj.scale(1 / cmd.dWidth, 1).resetScale();
        }
        else if (cmd.obj.type == "set"){ // 集合
          let childRotate = [];
          for(let i = 0; i < cmd.obj.length; i++){
            let elem = cmd.obj[i];
            childRotate[i] = elem.attrs["rotate"];
            if (childRotate[i]){
              elem.rotate(0, elem.getBBox().x + elem.getBBox().width / 2, elem.getBBox().y + elem.getBBox().height / 2);
            }
          }
          cmd.obj.scale(1 / cmd.dWidth, 1 / cmd.dHeight, cmd.obj.getBBox().x + cmd.obj.getBBox().width / 2, cmd.obj.getBBox().y + cmd.obj.getBBox().height / 2).resetScale();
          for(let i = 0; i < cmd.obj.length; i++){
            let elem = cmd.obj[i];
            if (childRotate[i]){
              elem.rotate(childRotate[i], elem.getBBox().x + elem.getBBox().width / 2, elem.getBBox().y + elem.getBBox().height / 2);
            }
          }
        }
        else{
          cmd.obj.scale(1 / cmd.dWidth, 1 / cmd.dHeight).resetScale();
        }
        if (currentObj == cmd.obj){
          currentObj = null;
          rotateBtn.hide();
          resizeSet.hide();
        }
      break;
      case "ResizeTextCommand":
        cmd.obj.attr("font-size", cmd.obj.attr("font-size") - cmd.dsize);
        if (currentObj == cmd.obj){
          currentObj = null;
          rotateBtn.hide();
          resizeSet.hide();
        }
      break;
      case "RotateObjectCommand":
        cmd.obj.rotate(cmd.startRotate, cmd.obj.getBBox().x + cmd.obj.getBBox().width / 2, cmd.obj.getBBox().y + cmd.obj.getBBox().height / 2);
        cmd.obj.attrs["rotate"] = cmd.startRotate;
        if (currentObj == cmd.obj){
          currentObj = null;
          rotateBtn.hide();
          resizeSet.hide();
        }
      break;
      case "StrokeWidthCommand":
        cmd.obj.attr("stroke-width", cmd.startWidth);
        if (currentObj == cmd.obj){
          currentObj = null;
          rotateBtn.hide();
          resizeSet.hide();
        }
      break;
      case "StrokeCommand":
        cmd.obj.attr("stroke", cmd.startStroke);
        if (currentObj == cmd.obj){
          currentObj = null;
          rotateBtn.hide();
          resizeSet.hide();
        }
      break;
      case "FillCommand":
        cmd.obj.attr("fill", cmd.startFill);
        if (currentObj == cmd.obj){
          currentObj = null;
          rotateBtn.hide();
          resizeSet.hide();
        }
      break;
      case "TextCommand":
        cmd.obj.attr("text", cmd.startText);
        if (currentObj == cmd.obj){
          currentObj = null;
          rotateBtn.hide();
          resizeSet.hide();
        }
      break;
      case "FontSizeCommand":
        cmd.obj.attr("font-size", cmd.startFontSize);
        if (currentObj == cmd.obj){
          currentObj = null;
          rotateBtn.hide();
          resizeSet.hide();
        }
      break;
      case "ImageCommand":
        cmd.obj.attr("src", cmd.startSrc);
        if (currentObj == cmd.obj){
          currentObj = null;
          rotateBtn.hide();
          resizeSet.hide();
        }
      break;
    }
    redos.push(cmd);
  }
}

/*
  * 重做
*/
function redo(){
  if (redos.length > 0){
    let cmd = redos.pop();
    switch(cmd.command){
      case "CopyObjectCommand":
        cmd.obj.show();
      break;
      case "DeleteObjectCommand":
        cmd.obj.hide();
      break;
      case "AddObjectCommand":
        cmd.obj.show();
      break;
      case "MoveObjectCommand":
        cmd.obj.translate(cmd.dx, cmd.dy);
        if (currentObj == cmd.obj){
          currentObj = null;
          rotateBtn.hide();
          resizeSet.hide();
        }
      break;
      case "ResizeObjectCommand":
        let width = cmd.obj.getBBox().width;
        let height = cmd.obj.getBBox().height;
        if (width == 0){
          cmd.obj.scale(1, cmd.dHeight).resetScale();
        }
        else if (height == 0){
          cmd.obj.scale(cmd.dWidth, 1).resetScale();
        }
        else if (cmd.obj.type == "set"){ // 集合
          let childRotate = [];
          for(let i = 0; i < cmd.obj.length; i++){
            let elem = cmd.obj[i];
            childRotate[i] = elem.attrs["rotate"];
            if (childRotate[i]){
              elem.rotate(0, elem.getBBox().x + elem.getBBox().width / 2, elem.getBBox().y + elem.getBBox().height / 2);
            }
          }
          cmd.obj.scale(cmd.dWidth, cmd.dHeight, cmd.obj.getBBox().x + cmd.obj.getBBox().width / 2, cmd.obj.getBBox().y + cmd.obj.getBBox().height / 2).resetScale();
          for(let i = 0; i < cmd.obj.length; i++){
            let elem = cmd.obj[i];
            if (childRotate[i]){
              elem.rotate(childRotate[i], elem.getBBox().x + elem.getBBox().width / 2, elem.getBBox().y + elem.getBBox().height / 2);
            }
          }
        }
        else{
          cmd.obj.scale(cmd.dWidth, cmd.dHeight).resetScale();
        }
        if (currentObj == cmd.obj){
          currentObj = null;
          rotateBtn.hide();
          resizeSet.hide();
        }
      break;
      case "ResizeTextCommand":
        cmd.obj.attr("font-size", cmd.obj.attr("font-size") + cmd.dsize);
        if (currentObj == cmd.obj){
          currentObj = null;
          rotateBtn.hide();
          resizeSet.hide();
        }
      break;
      case "RotateObjectCommand":
        cmd.obj.rotate(cmd.startRotate + cmd.rotate, cmd.obj.getBBox().x + cmd.obj.getBBox().width / 2, cmd.obj.getBBox().y + cmd.obj.getBBox().height / 2);
        cmd.obj.attrs["rotate"] = cmd.startRotate + cmd.rotate;
        if (currentObj == cmd.obj){
          currentObj = null;
          rotateBtn.hide();
          resizeSet.hide();
        }
      break;
      case "StrokeWidthCommand":
        cmd.obj.attr("stroke-width", cmd.width);
        if (currentObj == cmd.obj){
          currentObj = null;
          rotateBtn.hide();
          resizeSet.hide();
        }
      break;
      case "StrokeCommand":
        cmd.obj.attr("stroke", cmd.stroke);
        if (currentObj == cmd.obj){
          currentObj = null;
          rotateBtn.hide();
          resizeSet.hide();
        }
      break;
      case "FillCommand":
        cmd.obj.attr("fill", cmd.fill);
        if (currentObj == cmd.obj){
          currentObj = null;
          rotateBtn.hide();
          resizeSet.hide();
        }
      break;
      case "TextCommand":
        cmd.obj.attr("text", cmd.text);
        if (currentObj == cmd.obj){
          currentObj = null;
          rotateBtn.hide();
          resizeSet.hide();
        }
      break;
      case "FontSizeCommand":
        cmd.obj.attr("font-size", cmd.fontSize);
        if (currentObj == cmd.obj){
          currentObj = null;
          rotateBtn.hide();
          resizeSet.hide();
        }
      break;
      case "ImageCommand":
        cmd.obj.attr("src", cmd.src);
        if (currentObj == cmd.obj){
          currentObj = null;
          rotateBtn.hide();
          resizeSet.hide();
        }
      break;
    }
    undos.push(cmd);
  }
}

/*
  * 控制形变按钮位置与显示
  * params:各按钮是否显示
*/
function translateAndShowResizeBtn(nShow, eShow, sShow, wShow, neShow, nwShow, seShow, swShow, rotateShow){
  nResize.translate(objCenterX - nResize.attr("x"), objCenterY - 70 - nResize.attr("y"));
  eResize.translate(objCenterX + 70 - eResize.attr("x"), objCenterY - eResize.attr("y"));
  sResize.translate(objCenterX - sResize.attr("x"), objCenterY + 70 - sResize.attr("y"));
  wResize.translate(objCenterX - 70 - wResize.attr("x"), objCenterY - wResize.attr("y"));
  neResize.translate(objCenterX + 70 - neResize.attr("x"), objCenterY - 70 - neResize.attr("y"));
  nwResize.translate(objCenterX - 70 - nwResize.attr("x"), objCenterY - 70 - nwResize.attr("y"));
  seResize.translate(objCenterX + 70 - seResize.attr("x"), objCenterY + 70 - seResize.attr("y"));
  swResize.translate(objCenterX - 70 - swResize.attr("x"), objCenterY + 70 - swResize.attr("y"));
  rotateBtn.translate(objCenterX - rotateBtn.attr("x") -2, objCenterY - 80 - rotateBtn.attr("y") - 5);
  nShow ? nResize.show() : nResize.hide();
  eShow ? eResize.show() : eResize.hide();
  sShow ? sResize.show() : sResize.hide();
  wShow ? wResize.show() : wResize.hide();
  neShow ? neResize.show() : neResize.hide();
  nwShow ? nwResize.show() : nwResize.hide();
  seShow ? seResize.show() : seResize.hide();
  swShow ? swResize.show() : swResize.hide();
  rotateShow ? rotateBtn.show() : rotateBtn.hide();
}

/*
  * 控制形变按钮位置
*/
function translateResizeBtn(){
  nResize.translate(objCenterX - nResize.attr("x"), objCenterY - 70 - nResize.attr("y"));
  eResize.translate(objCenterX + 70 - eResize.attr("x"), objCenterY - eResize.attr("y"));
  sResize.translate(objCenterX - sResize.attr("x"), objCenterY + 70 - sResize.attr("y"));
  wResize.translate(objCenterX - 70 - wResize.attr("x"), objCenterY - wResize.attr("y"));
  neResize.translate(objCenterX + 70 - neResize.attr("x"), objCenterY - 70 - neResize.attr("y"));
  nwResize.translate(objCenterX - 70 - nwResize.attr("x"), objCenterY - 70 - nwResize.attr("y"));
  seResize.translate(objCenterX + 70 - seResize.attr("x"), objCenterY + 70 - seResize.attr("y"));
  swResize.translate(objCenterX - 70 - swResize.attr("x"), objCenterY + 70 - swResize.attr("y"));
  rotateBtn.translate(objCenterX - rotateBtn.attr("x") -2, objCenterY - 80 - rotateBtn.attr("y") - 5);
}

/*
  * 初始化形变按钮跟随位移临时参数
*/
function initResizeFlowMove(){
  nResize.tempx = 0;
  nResize.tempy = 0;
  eResize.tempx = 0;
  eResize.tempy = 0;
  sResize.tempx = 0;
  sResize.tempy = 0;
  wResize.tempx = 0;
  wResize.tempy = 0;
  neResize.tempx = 0;
  neResize.tempy = 0;
  nwResize.tempx = 0;
  nwResize.tempy = 0;
  seResize.tempx = 0;
  seResize.tempy = 0;
  swResize.tempx = 0;
  swResize.tempy = 0;
  rotateBtn.tempx = 0;
  rotateBtn.tempy = 0;
}

/*
  * 形变按钮跟随键盘上下左右键位移
  * dx：相对起始点的x位移,dy:相对起始点的y位移
*/
function resizeFlowKeyMove(dx, dy){
  resizeSet.translate(dx, dy);
  rotateBtn.translate(dx, dy);
}

/*
  * 形变按钮跟随位移
  * dx：相对起始点的x位移,dy:相对起始点的y位移
*/
function resizeFlowMove(dx, dy){
  nResize.translate(dx - nResize.tempx, dy - nResize.tempy);
  nResize.tempx = dx;
  nResize.tempy = dy; 
  eResize.translate(dx - eResize.tempx, dy - eResize.tempy);
  eResize.tempx = dx;
  eResize.tempy = dy; 
  sResize.translate(dx - sResize.tempx, dy - sResize.tempy);
  sResize.tempx = dx;
  sResize.tempy = dy; 
  wResize.translate(dx - wResize.tempx, dy - wResize.tempy);
  wResize.tempx = dx;
  wResize.tempy = dy;
  neResize.translate(dx - neResize.tempx, dy - neResize.tempy);
  neResize.tempx = dx;
  neResize.tempy = dy; 
  nwResize.translate(dx - nwResize.tempx, dy - nwResize.tempy);
  nwResize.tempx = dx;
  nwResize.tempy = dy; 
  seResize.translate(dx - seResize.tempx, dy - seResize.tempy);
  seResize.tempx = dx;
  seResize.tempy = dy; 
  swResize.translate(dx - swResize.tempx, dy - swResize.tempy);
  swResize.tempx = dx;
  swResize.tempy = dy;
  rotateBtn.translate(dx - rotateBtn.tempx, dy - rotateBtn.tempy);
  rotateBtn.tempx = dx;
  rotateBtn.tempy = dy;
}

/*
  * 画矩形
  * params:画布,矩形横坐标,矩形纵坐标,矩形宽,矩形高,矩形边框,填充颜色,边框颜色,旋转角度
*/
function drawRect(paper, startX, startY, w, h, s, fill, stroke, rotate){
  //创建矩形
  let rect = paper.rect(startX, startY, w , h).attr({'fill':fill, 'stroke':stroke,'stroke-width':s}).drag(rectMove, rectStartMove, rectEndMove).toBack();
  /*
  * 定义拖动外部矩形的开始移动，移动和结束移动事件
  * 注：dx：相对起始点的x位移,dy:相对起始点的y位移,x:鼠标的 x轴位置,y:鼠标的 y轴位置,event:DOM事件对象,e.clientX:当前鼠标x坐标,e.clientY：当前鼠标Y坐标
  */
  function rectStartMove(dx, dy){
    //为元素自定义属性并赋值
    this.tempx = 0;
    this.tempy = 0;     
    initResizeFlowMove();
  }

  function rectMove(dx,dy,x,y){
    this.translate(dx - this.tempx, dy - this.tempy);
    this.tempx = dx;
    this.tempy = dy;
    resizeFlowMove(dx, dy);
    // 设置属性x/y值
    propertyForm.x = currentObj.getBBox().x;
    propertyForm.y = currentObj.getBBox().y;
  }

  function rectEndMove(){
    this.animate({"fill-opacity": 1}, 300);
    undos.push({ command: "MoveObjectCommand", obj: rect, dx: this.tempx, dy: this.tempy });
  }

  if (rotate){
    rect.rotate(rotate, startX + w /2, startY + h / 2)
    rect.attrs["rotate"] = rotate
  }

  // 改变鼠标悬浮的状态
  rect.hover(function(){
    this.attr('cursor','move');
  },function(){});

  rect.mousedown(function(){
    currentObj = rect;
    objCenterX = currentObj.getBBox().x + currentObj.getBBox().width / 2;
    objCenterY = currentObj.getBBox().y + currentObj.getBBox().height / 2;
    translateAndShowResizeBtn(true, true, true, true, true, true, true, true, true);
    // 属性回写
    propertyForm.width = currentObj.attr("width");
    propertyForm.height = currentObj.attr("height");
    propertyForm.strokeWidth = currentObj.attr("stroke-width");
    propertyForm.stroke = currentObj.attr("stroke");
    propertyForm.fill = currentObj.attr("fill");
    propertyForm.x = currentObj.getBBox().x;
    propertyForm.y = currentObj.getBBox().y;
    propertyForm.rotate = currentObj.attrs["rotate"] ? currentObj.attrs["rotate"] : 0;
  },function(){});

  return rect;
}

/*
  * 画圆形
  * params:画布,圆形横坐标,圆形纵坐标,圆形半径,圆形边框,填充颜色,边框颜色
*/
function drawCircle(paper, startX, startY, radius, s, fill, stroke){
  //创建圆形
  let circle = paper.circle(startX, startY, radius).attr({'fill':fill, 'stroke':stroke,'stroke-width':s}).drag(circleMove, circleStartMove, circleEndMove).toBack();

  let ddx = 0;
  let ddy = 0;
  function circleStartMove(dx, dy){
    this.tempx = this.attr("cx");
    this.tempy = this.attr("cy");    
    initResizeFlowMove(); 
    ddx = 0;
    ddy = 0;
  }

  function circleMove(dx, dy, x, y){
    let attr = {'cx': this.tempx + dx, 'cy': this.tempy + dy ,'cursor':'move'};
    this.attr(attr);
    resizeFlowMove(dx, dy);
    ddx = dx;
    ddy = dy;
    // 设置属性x/y值
    propertyForm.x = currentObj.getBBox().x;
    propertyForm.y = currentObj.getBBox().y;
  }

  function circleEndMove(){
    this.animate({"fill-opacity": 1}, 300);
    undos.push({ command: "MoveObjectCommand", obj: circle, dx: ddx, dy: ddy });
  }

  circle.hover(function(){
    this.attr('cursor','move');
  },function(){});

  circle.mousedown(function(){
    currentObj = circle;
    objCenterX = currentObj.getBBox().x + currentObj.getBBox().width / 2;
    objCenterY = currentObj.getBBox().y + currentObj.getBBox().height / 2;
    translateAndShowResizeBtn(false, false, false, false, true, true, true, true, false);
    // 属性回写
    propertyForm.radius = currentObj.attr("r");
    propertyForm.strokeWidth = currentObj.attr("stroke-width");
    propertyForm.stroke = currentObj.attr("stroke");
    propertyForm.fill = currentObj.attr("fill");
    propertyForm.x = currentObj.getBBox().x;
    propertyForm.y = currentObj.getBBox().y;
    propertyForm.rotate = currentObj.attrs["rotate"] ? currentObj.attrs["rotate"] : 0;
  },function(){});

  return circle;
}

/*
  * 画椭圆
  * params:画布,椭圆横坐标,椭圆纵坐标,椭圆宽度,椭圆高度,边框,填充颜色,边框颜色,旋转角度
*/
function drawEllipse(paper, startX, startY, w, h, s, fill, stroke, rotate){
  //创建椭圆
  let ellipse = paper.ellipse(startX, startY, w, h).attr({'fill':fill, 'stroke':stroke,'stroke-width':s})
    .drag(ellipseMove, ellipseStartMove, ellipseEndMove)
    .toBack();

  function ellipseStartMove(dx, dy){
    this.tempx = 0;
    this.tempy = 0;    
    initResizeFlowMove(); 
  }

  function ellipseMove(dx, dy, x, y){
    this.translate(dx - this.tempx, dy - this.tempy);
    this.tempx = dx;
    this.tempy = dy;
    resizeFlowMove(dx, dy);
    // 设置属性x/y值
    propertyForm.x = currentObj.getBBox().x;
    propertyForm.y = currentObj.getBBox().y;
  }

  function ellipseEndMove(){
    this.animate({"fill-opacity": 1}, 300);
    undos.push({ command: "MoveObjectCommand", obj: ellipse, dx: this.tempx, dy: this.tempy });
  }

  if (rotate){
    ellipse.rotate(rotate, startX + w /2, startY + h / 2)
    ellipse.attrs["rotate"] = rotate
  }

  ellipse.hover(function(){
    this.attr('cursor','move');
  },function(){});

  ellipse.mousedown(function(){
    currentObj = ellipse;
    objCenterX = currentObj.getBBox().x + currentObj.getBBox().width / 2;
    objCenterY = currentObj.getBBox().y + currentObj.getBBox().height / 2;
    translateAndShowResizeBtn(true, true, true, true, true, true, true, true, true);
    // 属性回写
    propertyForm.width = currentObj.getBBox().width;
    propertyForm.height = currentObj.getBBox().height;
    propertyForm.strokeWidth = currentObj.attr("stroke-width");
    propertyForm.stroke = currentObj.attr("stroke");
    propertyForm.fill = currentObj.attr("fill");
    propertyForm.x = currentObj.getBBox().x;
    propertyForm.y = currentObj.getBBox().y;
    propertyForm.rotate = currentObj.attrs["rotate"] ? currentObj.attrs["rotate"] : 0;
  },function(){});

  return ellipse;
}

/*
  * 画三角（等腰三角形）
  * params:画布,中心点横坐标,中心点纵坐标,宽度,高度,边框,填充颜色,边框颜色,旋转角度
*/
function drawTriangle(paper, startX, startY, w, h, s, fill, stroke, rotate){
  let path = "M" + (startX - w / 2) + " " + (startY + h / 2) + "L" + startX + " " + (startY - h / 2) + "L" + (startX + w / 2) + " " + (startY + h / 2) + "Z";
  let triangle = paper.path(path).attr({'fill':fill, 'stroke':stroke, 'stroke-width':s})
    .drag(triangleMove, triangleStartMove, triangleEndMove)
    .toBack();

  function triangleStartMove(dx, dy){
    this.tempx = 0;
    this.tempy = 0; 
    initResizeFlowMove();
  }

  function triangleMove(dx,dy,x,y){
    this.translate(dx - this.tempx, dy - this.tempy);
    this.tempx = dx;
    this.tempy = dy;
    resizeFlowMove(dx, dy);
    // 设置属性x/y值
    propertyForm.x = currentObj.getBBox().x;
    propertyForm.y = currentObj.getBBox().y;
  }

  function triangleEndMove(){
    this.animate({"fill-opacity": 1}, 300);
    undos.push({ command: "MoveObjectCommand", obj: triangle, dx: this.tempx, dy: this.tempy });
  }

  if (rotate){
    triangle.rotate(rotate, startX, startY)
    triangle.attrs["rotate"] = rotate
  }

  //改变鼠标悬浮的状态
  triangle.hover(function(){
    this.attr('cursor','move');
  },function(){});

  triangle.mousedown(function(){
    currentObj = triangle;
    objCenterX = currentObj.getBBox().x + currentObj.getBBox().width / 2;
    objCenterY = currentObj.getBBox().y + currentObj.getBBox().height / 2;
    translateAndShowResizeBtn(true, true, true, true, true, true, true, true, true);
    // 属性回写
    let path = currentObj.attr("path");
    let width = path[2][1] - path[0][1];
    let height = path[0][2] - path[1][2];
    propertyForm.width = width;
    propertyForm.height = height;
    propertyForm.strokeWidth = currentObj.attr("stroke-width");
    propertyForm.stroke = currentObj.attr("stroke");
    propertyForm.fill = currentObj.attr("fill");
    propertyForm.x = currentObj.getBBox().x;
    propertyForm.y = currentObj.getBBox().y;
    propertyForm.rotate = currentObj.attrs["rotate"] ? currentObj.attrs["rotate"] : 0;
  },function(){});

  return triangle;
}

/*
  * 画横线
  * params:画布,中心点横坐标,中心点纵坐标,长度,线粗细,线颜色,旋转角度
*/
function drawLine(paper, startX, startY, l, s, stroke, rotate){
  let path = "M" + (startX - l / 2) + " " + startY + "L" + (startX + l / 2) + " " + startY;
  let line = paper.path(path).attr({'stroke':stroke, 'stroke-width':s}).drag(lineMove, lineStartMove, lineEndMove).toBack();

  function lineStartMove(dx, dy){
    this.tempx = 0;
    this.tempy = 0; 
    initResizeFlowMove();
  }

  function lineMove(dx,dy,x,y){
    this.translate(dx - this.tempx, dy - this.tempy);
    this.tempx = dx;
    this.tempy = dy;
    resizeFlowMove(dx, dy);
    // 设置属性x/y值
    propertyForm.x = currentObj.getBBox().x;
    propertyForm.y = currentObj.getBBox().y;
  }

  function lineEndMove(){
    this.animate({"fill-opacity": 1}, 300);
    undos.push({ command: "MoveObjectCommand", obj: line, dx: this.tempx, dy: this.tempy });
  }

  if (rotate){
    line.rotate(rotate, startX, startY)
    line.attrs["rotate"] = rotate
  }

  //改变鼠标悬浮的状态
  line.hover(function(){
    this.attr('cursor','move');
  },function(){});

  line.mousedown(function(){
    currentObj = line;
    objCenterX = currentObj.getBBox().x + currentObj.getBBox().width / 2;
    objCenterY = currentObj.getBBox().y + currentObj.getBBox().height / 2;
    translateAndShowResizeBtn(false, true, false, true, false, false, false, false, true);
    // 属性回写
    let path = currentObj.attr("path");
    let width = path[1][1] - path[0][1];
    propertyForm.width = width;
    propertyForm.strokeWidth = currentObj.attr("stroke-width");
    propertyForm.stroke = currentObj.attr("stroke");
    propertyForm.x = currentObj.getBBox().x;
    propertyForm.y = currentObj.getBBox().y;
    propertyForm.rotate = currentObj.attrs["rotate"] ? currentObj.attrs["rotate"] : 0;
  },function(){});

  return line;
}

/*
  * 画竖线
  * params:画布,中心点横坐标,中心点纵坐标,长度,线粗细,线颜色,旋转角度
*/
function drawVerticalLine(paper, startX, startY, l, s, stroke, rotate){
  let path = "M" + startX + " " + (startY - l / 2) + "L" + startX + " " + (startY + l / 2);
  let line = paper.path(path).attr({'stroke':stroke, 'stroke-width':s}).drag(lineMove, lineStartMove, lineEndMove).toBack();

  function lineStartMove(dx, dy){
    this.tempx = 0;
    this.tempy = 0; 
    initResizeFlowMove();
  }

  function lineMove(dx,dy,x,y){
    this.translate(dx - this.tempx, dy - this.tempy);
    this.tempx = dx;
    this.tempy = dy;
    resizeFlowMove(dx, dy);
    // 设置属性x/y值
    propertyForm.x = currentObj.getBBox().x;
    propertyForm.y = currentObj.getBBox().y;
  }

  function lineEndMove(){
    this.animate({"fill-opacity": 1}, 300);
    undos.push({ command: "MoveObjectCommand", obj: line, dx: this.tempx, dy: this.tempy });
  }

  if (rotate){
    line.rotate(rotate, startX, startY)
    line.attrs["rotate"] = rotate
  }

  //改变鼠标悬浮的状态
  line.hover(function(){
    this.attr('cursor','move');
  },function(){});

  line.mousedown(function(){
    currentObj = line;
    objCenterX = currentObj.getBBox().x + currentObj.getBBox().width / 2;
    objCenterY = currentObj.getBBox().y + currentObj.getBBox().height / 2;
    translateAndShowResizeBtn(true, false, true, false, false, false, false, false, true);
    // 属性回写
    let path = currentObj.attr("path");
    let height = path[1][2] - path[0][2];
    propertyForm.height = height;
    propertyForm.strokeWidth = currentObj.attr("stroke-width");
    propertyForm.stroke = currentObj.attr("stroke");
    propertyForm.x = currentObj.getBBox().x;
    propertyForm.y = currentObj.getBBox().y;
    propertyForm.rotate = currentObj.attrs["rotate"] ? currentObj.attrs["rotate"] : 0;
  },function(){});

  return line;
}

/*
  * 画图片
  * params:画布,中心点横坐标,中心点纵坐标,宽度,高度,边框,旋转角度
*/
function drawImage(paper, startX, startY, url, w, h, s, rotate){
  let image = paper.image(url, startX, startY, w, h).attr({'stroke-width':s}).drag(imageMove, imageStartMove, imageEndMove).toBack();

  function imageStartMove(dx, dy){
    this.tempx = 0;
    this.tempy = 0; 
    initResizeFlowMove();
  }

  function imageMove(dx,dy,x,y){
    this.translate(dx - this.tempx, dy - this.tempy);
    this.tempx = dx;
    this.tempy = dy;
    resizeFlowMove(dx, dy);
    // 设置属性x/y值
    propertyForm.x = currentObj.getBBox().x;
    propertyForm.y = currentObj.getBBox().y;
  }

  function imageEndMove(){
    this.animate({"fill-opacity": 1}, 300);
    undos.push({ command: "MoveObjectCommand", obj: image, dx: this.tempx, dy: this.tempy });
  }

  if (rotate){
    image.rotate(rotate, startX + w /2, startY + h / 2)
    image.attrs["rotate"] = rotate
  }

  //改变鼠标悬浮的状态
  image.hover(function(){
    this.attr('cursor','move');
  },function(){});

  image.mousedown(function(){
    currentObj = image;
    objCenterX = currentObj.getBBox().x + currentObj.getBBox().width / 2;
    objCenterY = currentObj.getBBox().y + currentObj.getBBox().height / 2;
    translateAndShowResizeBtn(false, false, false, false, true, true, true, true, true);
    // 属性回写
    propertyForm.width = currentObj.attr("width");
    propertyForm.height = currentObj.attr("height");
    propertyForm.strokeWidth = currentObj.attr("stroke-width");
    propertyForm.img = currentObj.attr("src");
    propertyForm.x = currentObj.getBBox().x;
    propertyForm.y = currentObj.getBBox().y;
    propertyForm.rotate = currentObj.attrs["rotate"] ? currentObj.attrs["rotate"] : 0;
  },function(){});

  return image;
}

/*
  * 画文字
  * params:画布,中心点横坐标,中心点纵坐标,文字内容,文字大小,线宽,填充颜色,边框颜色,旋转角度,数据源,字段
*/
function drawText(paper, startX, startY, content, fontSize, strokeWidth, fill, stroke, rotate, dataSource, column){
  let text = paper.text(startX, startY, content)
    .attr({stroke: stroke, "stroke-width": strokeWidth,"font-size": fontSize,"text-anchor": "middle", "fill": fill})
    .drag(textMove, textStartMove, textEndMove)
    .toBack();

  function textStartMove(dx, dy){
    this.tempx = 0;
    this.tempy = 0; 
    initResizeFlowMove();
  }

  function textMove(dx,dy,x,y){
    this.translate(dx - this.tempx, dy - this.tempy);
    this.tempx = dx;
    this.tempy = dy;
    resizeFlowMove(dx, dy);
    // 设置属性x/y值
    propertyForm.x = currentObj.getBBox().x;
    propertyForm.y = currentObj.getBBox().y;
  }

  function textEndMove(){
    this.animate({"fill-opacity": 1}, 300);
    undos.push({ command: "MoveObjectCommand", obj: text, dx: this.tempx, dy: this.tempy });
  }

  if (rotate){
    text.rotate(rotate, startX, startY)
    text.attrs["rotate"] = rotate
  }

  if (dataSource){
    text.attrs["dataSource"] = dataSource
  }

  if (column){
    text.attrs["column"] = column
  }

  //改变鼠标悬浮的状态
  text.hover(function(){
    this.attr('cursor','move');
  },function(){});

  text.mousedown(function(){
    currentObj = text;
    objCenterX = currentObj.getBBox().x + currentObj.getBBox().width / 2 ;
    objCenterY = currentObj.getBBox().y + currentObj.getBBox().height / 2;
    translateAndShowResizeBtn(false, false, false, false, false, false, false, false, true);
    // 属性回写
    propertyForm.text = currentObj.attr("text");
    propertyForm.fontSize = currentObj.attr("font-size");
    propertyForm.strokeWidth = currentObj.attr("stroke-width");
    propertyForm.stroke = currentObj.attr("stroke");
    propertyForm.fill = currentObj.attr("fill");
    propertyForm.x = currentObj.getBBox().x;
    propertyForm.y = currentObj.getBBox().y;
    propertyForm.rotate = currentObj.attrs["rotate"] ? currentObj.attrs["rotate"] : 0;
  },function(){});

  return text;
}

/*
  * 画柱状图
  * params:画布,文字大小,线宽,填充颜色,边框颜色,数据源,x轴字段,y轴字段
*/
function drawBar(paper, fontSize, strokeWidth, fill, stroke, dataSource, xColumn, yColumn){
  let set = paper.set();
  let xAxis = ["2022", "2023", "2024", "2025", "2026"];
  let xName = "年份";
  let yAxis = [34, 55, 77, 33, 46];
  let yName = "产值(百万元)";
  makeBarData(set, xAxis, xName, yAxis, yName);
  set.attr("font-size", fontSize).attr("stroke-width", strokeWidth).attr("fill", fill).attr("stroke", stroke);

  set.drag(setMove, setStartMove, setEndMove).toBack();

  let ddx = 0;
  let ddy = 0;
  function setStartMove(dx, dy){
    for(let i = 0; i < set.length; i++){
      var item = set[i];
      item.tempx = 0;
      item.tempy = 0; 
    }
    initResizeFlowMove();
    ddx = 0;
    ddy = 0;
  }

  function setMove(dx, dy, x, y){
    for(let i = 0; i < set.length; i++){
      var item = set[i];
      item.translate(dx - item.tempx, dy - item.tempy);
      item.tempx = dx;
      item.tempy = dy;
    }
    resizeFlowMove(dx, dy);
    ddx = dx;
    ddy = dy;
    // 设置属性x/y值
    propertyForm.x = currentObj.getBBox().x;
    propertyForm.y = currentObj.getBBox().y;
  }

  function setEndMove(){
    for(var i = 0; i < set.length; i++){
      var item = set[i];
      item.animate({"fill-opacity": 1}, 300);
    }
    undos.push({ command: "MoveObjectCommand", obj: set, dx: ddx, dy: ddy });
  }

  //改变鼠标悬浮的状态
  set.hover(function(){
    this.attr('cursor','move');
  },function(){});

  set.mousedown(function(){
    currentObj = set;
    objCenterX = currentObj.getBBox().x + currentObj.getBBox().width / 2 ;
    objCenterY = currentObj.getBBox().y + currentObj.getBBox().height / 2;
    translateAndShowResizeBtn(false, false, false, false, true, true, true, true, false);
    propertyForm.x = currentObj.getBBox().x;
    propertyForm.y = currentObj.getBBox().y;
    propertyForm.rotate = 0;
  },function(){});

  return set;
}

function makeBarData(set, xAxis, xName, yAxis, yName){
  if (xAxis.length != yAxis.length){
    ElMessageBox.warning("请检查数据源");
    return;
  }
  let width = xAxis.length * 60 + 60;
  let height = 200;
  let maxValue = findMax(yAxis);
  let rate = 1;
  if (maxValue > height){
    rate = maxValue / height;
  }
  set.push(
    // 横轴
    paper.path("M0 200L" + width + " 200"),
    paper.path("M" + width + " 200L" + (width - 6) + " 196"),
    paper.path("M" + width + " 200L" + (width - 6) + " 204"),
    paper.text(width - 20, 220, xName),
    // 纵轴
    paper.path("M0 200L0 0"),
    paper.path("M0 0L-4 6"),
    paper.path("M0 0L4 6"),
    paper.text(-20, 20, yName),
  )

  for(let i = 0; i < xAxis.length; i++){
    set.push(paper.text(i * 60 + 60, 220, xAxis[i]));
    let high = yAxis[i] / rate;
    let x = i * 60 + 60 - 15;
    let y = height - high;
    let w = 30;
    let h = high;
    set.push(paper.rect(x, y, w, h));
    set.push(paper.text(i * 60 + 60, y - 10, yAxis[i]))
  }
}

function findMax(arr) {
  let max = arr[0];
  for (let i = 1; i < arr.length; i++) {
    if (arr[i] > max) {
      max = arr[i];
    }
  }
  return max;
}

// 断路器(弃用)
function drawBreaker(startX, startY, color){
  var breaker = paper.set();
  breaker.push(
    paper.path("M5 0L5 6"),
    paper.path("M0 10L5 6L10 10"),
    paper.path("M0 14L5 10L10 14"),
    paper.path("M5 10L5 22"),
    paper.rect(1, 22, 8, 16),
    paper.path("M5 38L5 50"),
    paper.path("M0 46L5 50L10 46"),
    paper.path("M0 50L5 54L10 50"),
    paper.path("M5 54L5 60"),
  )
  breaker.drag(breakerMove, breakerStartMove, breakerEndMove).toBack();
  breaker.translate(startX, startY);

  // 左下角缩放
  var outerLeftBottom = paper.rect(-30, 90, 5, 5).drag(leftBottomMove, leftBottomStartMove, leftBottomEndMove).toBack();
  outerLeftBottom.attr({
    fill: "black"
  })
  outerLeftBottom.hide();
  outerLeftBottom.translate(startX, startY);

  // 右下角缩放
  var outerRightBottom = paper.rect(30, 90, 5, 5).drag(rightBottomMove, rightBottomStartMove, rightBottomEndMove).toBack();
  outerRightBottom.attr({
    fill: "black"
  })
  outerRightBottom.hide();
  outerRightBottom.translate(startX, startY);

  // 旋转
  var outerRotate = paper.rect(0, -30, 5, 5).drag(rotateMove, rotateStartMove, rotateEndMove).toBack();
  outerRotate.attr({
    fill: "black"
  })
  outerRotate.hide();
  outerRotate.translate(startX, startY);

  function breakerStartMove(dx, dy){
    for(var i = 0; i < breaker.length; i++){
      var item = breaker[i];
      item.tempx = 0;
      item.tempy = 0; 
    }
    outerLeftBottom.tempx = 0;
    outerLeftBottom.tempy = 0; 
    outerRightBottom.tempx = 0;
    outerRightBottom.tempy = 0;
    outerRotate.tempx = 0;
    outerRotate.tempy = 0;
  }

  function breakerMove(dx, dy, x, y){
    for(var i = 0; i < breaker.length; i++){
      var item = breaker[i];
      item.translate(dx - item.tempx, dy - item.tempy);
      item.tempx = dx;
      item.tempy = dy;
    }
    startX = startX + dx;
    startY = startY + dy;
    outerLeftBottom.translate(dx - outerLeftBottom.tempx, dy - outerLeftBottom.tempy);
    outerLeftBottom.tempx = dx;
    outerLeftBottom.tempy = dy; 
    outerRightBottom.translate(dx - outerRightBottom.tempx, dy - outerRightBottom.tempy);
    outerRightBottom.tempx = dx;
    outerRightBottom.tempy = dy; 
    outerRotate.translate(dx - outerRotate.tempx, dy - outerRotate.tempy);
    outerRotate.tempx = dx;
    outerRotate.tempy = dy; 
  }

  function breakerEndMove(){
    for(var i = 0; i < breaker.length; i++){
      var item = breaker[i];
      item.animate({"fill-opacity": 1}, 300);
    }
  }

  var leftBottomX = 0;
  var leftBottomY = 0;
  var beforeMoveW = 20;
  function leftBottomStartMove(){
    this.mx = this.attr("x");
    this.my = this.attr("y");

    leftBottomX = this.attr("x");
    leftBottomY = this.attr("y");
  }

  function leftBottomMove(dx,dy,x,y){
    dy = -dx;
    breaker.scale((beforeMoveW - dx) / 20, (beforeMoveW - dx) / 20, this.mx + 50, this.my - 110);
    var attr = {'x': this.mx + dx, 'y': this.my + dy};
    //this.attr(attr);
  }

  function leftBottomEndMove(e){
    beforeMoveW = beforeMoveW * (1 - (e.clientX  - 510 - leftBottomX) / beforeMoveW);
    this.animate({"fill-opacity": 1}, 300);
  }

  var rightBottomX = 0;
  var rightBottomY = 0;
  function rightBottomStartMove(){
    this.mx = this.attr("x");
    this.my = this.attr("y");

    rightBottomX = this.attr("x");
    rightBottomY = this.attr("y");
  }

  function rightBottomMove(dx,dy,x,y){
    dy = -dx;
    breaker.scale((beforeMoveW + dx) / 20, (beforeMoveW + dx) / 20, this.mx + 50, this.my - 110);
    var attr = {'x': this.mx + dx, 'y': this.my + dy};
    //this.attr(attr);
  }

  function rightBottomEndMove(e){
    beforeMoveW = beforeMoveW * (1 + (e.clientX  - 510 - rightBottomX) / beforeMoveW);
    this.animate({"fill-opacity": 1}, 300);
  }

  var rotateX = 0;
  var rotateY = 0;
  function rotateStartMove(){
    this.mx = this.attr("x");
    this.my = this.attr("y");

    rotateX = this.attr("x");
    rotateY = this.attr("y");
  }

  function rotateMove(dx,dy,x,y){
    breaker.rotate(dx / 10, startX, startY);
  }

  function rotateEndMove(e){
    this.animate({"fill-opacity": 1}, 300);
  }

  breaker.hover(function(){
    breaker.attr('cursor','move');
  },function(){});

  outerLeftBottom.hover(function(){
    outerLeftBottom.attr('cursor','ne-resize');
  },function(){});
  outerRightBottom.hover(function(){
    outerRightBottom.attr('cursor','nw-resize');
  },function(){});
  outerRotate.hover(function(){
    outerRotate.attr('cursor','resize');
  },function(){});

  breaker.click(function(){
    outerLeftBottom.show();
    outerRightBottom.show();
    outerRotate.show();
  })
}

/*
  * 画用户自定义组件
  * params:组件元素集
*/
function drawUserObj(elements){
  let set = paper.set();
  parseUserObj(set, elements);
  
  set.drag(setMove, setStartMove, setEndMove).toBack();

  let ddx = 0;
  let ddy = 0;
  function setStartMove(dx, dy){
    for(let i = 0; i < set.length; i++){
      var item = set[i];
      item.tempx = 0;
      item.tempy = 0; 
    }
    initResizeFlowMove();
    ddx = 0;
    ddy = 0;
  }

  function setMove(dx, dy, x, y){
    for(let i = 0; i < set.length; i++){
      var item = set[i];
      item.translate(dx - item.tempx, dy - item.tempy);
      item.tempx = dx;
      item.tempy = dy;
    }
    resizeFlowMove(dx, dy);
    ddx = dx;
    ddy = dy;
    // 设置属性x/y值
    propertyForm.x = currentObj.getBBox().x;
    propertyForm.y = currentObj.getBBox().y;
  }

  function setEndMove(){
    for(var i = 0; i < set.length; i++){
      var item = set[i];
      item.animate({"fill-opacity": 1}, 300);
    }
    undos.push({ command: "MoveObjectCommand", obj: set, dx: ddx, dy: ddy });
  }

  //改变鼠标悬浮的状态
  set.hover(function(){
    this.attr('cursor','move');
  },function(){});

  set.mousedown(function(){
    currentObj = set;
    objCenterX = currentObj.getBBox().x + currentObj.getBBox().width / 2 ;
    objCenterY = currentObj.getBBox().y + currentObj.getBBox().height / 2;
    translateAndShowResizeBtn(false, false, false, false, true, true, true, true, false);
    propertyForm.x = currentObj.getBBox().x;
    propertyForm.y = currentObj.getBBox().y;
    propertyForm.rotate = 0;
  },function(){});

  return set;
}

/*
  * 遍历解析组件元素，汇总到set集合
  * set:组件元素集合
  * elements:组件元素
*/
function parseUserObj(set, elements){
  for(let i = 0; i < elements.length; i++){
    let element = elements[i];
    switch (element.type){
      case "rect":
        let rect = paper.rect(element.attrs["x"], element.attrs["y"], element.attrs["width"] , element.attrs["height"])
          .attr({'fill':element.attrs["fill"], 'stroke':element.attrs["stroke"],'stroke-width':element.attrs["stroke-width"]});
        if (element.attrs["rotate"]){
          rect.rotate(element.attrs["rotate"], element.attrs["x"] + element.attrs["width"] /2, element.attrs["y"] + element.attrs["height"] / 2);
          rect.attrs["rotate"] = element.attrs["rotate"];
        }
        set.push(rect);
      break;
      case "circle":
        let circle = paper.circle(element.attrs["cx"], element.attrs["cy"], element.attrs["r"])
          .attr({'fill':element.attrs["fill"], 'stroke':element.attrs["stroke"],'stroke-width':element.attrs["stroke-width"]});
        set.push(circle);
      break;
      case "ellipse":
        let ellipse = paper.ellipse(element.attrs["cx"], element.attrs["cy"], element.attrs["rx"], element.attrs["ry"])
          .attr({'fill':element.attrs["fill"], 'stroke':element.attrs["stroke"],'stroke-width':element.attrs["stroke-width"]});
        if (element.attrs["rotate"]){
          ellipse.rotate(element.attrs["rotate"], element.attrs["cx"] + element.attrs["rx"] /2, element.attrs["cy"] + element.attrs["ry"] / 2);
          ellipse.attrs["rotate"] = element.attrs["rotate"]
        }
        set.push(ellipse);
      break;
      case "triangle":
        let trianglePath = element.attrs["path"];
        let width = trianglePath[2][1] - trianglePath[0][1];
        let height = trianglePath[0][2] - trianglePath[1][2];
        let x = trianglePath[0][1] + width / 2;
        let y = trianglePath[0][2] - height / 2;

        let trianglePathStr = "M" + trianglePath[0][1] + " " + trianglePath[0][2] + "L" + trianglePath[1][1] + " " 
          + trianglePath[1][2] + "L" + trianglePath[2][1] + " " + trianglePath[2][2] + "Z";
        let triangle = paper.path(trianglePathStr).attr({'fill':element.attrs["fill"], 'stroke':element.attrs["stroke"],'stroke-width':element.attrs["stroke-width"]});
        if (element.attrs["rotate"]){
          triangle.rotate(element.attrs["rotate"], x, y)
          triangle.attrs["rotate"] = element.attrs["rotate"]
        }
        set.push(triangle);
      break;
      case "line":
        let linePath = element.attrs["path"];
        let lineWidth = linePath[1][1] - linePath[0][1];
        let lineX = linePath[0][1] + lineWidth / 2;
        let lineY = linePath[0][2];
        let linePathStr = "M" + linePath[0][1] + " " + linePath[0][2] + "L" + linePath[1][1] + " " + linePath[1][2];
        let line = paper.path(linePathStr).attr({'stroke':element.attrs["stroke"], 'stroke-width':element.attrs["stroke-width"]});
        if (element.attrs["rotate"]){
          line.rotate(element.attrs["rotate"], lineX, lineY)
          line.attrs["rotate"] = element.attrs["rotate"]
        }
        set.push(line);
      break;
      case "vline":
        let vlinePath = element.attrs["path"];
        let vlineHeight = vlinePath[1][2] - vlinePath[0][2];
        let vlineX = vlinePath[0][1];
        let vlineY = vlinePath[0][2] + vlineHeight / 2;
        let vlinePathStr = "M" + vlinePath[0][1] + " " + vlinePath[0][2] + "L" + vlinePath[1][1] + " " + vlinePath[1][2];
        let vline = paper.path(vlinePathStr).attr({'stroke':element.attrs["stroke"], 'stroke-width':element.attrs["stroke-width"]});
        if (element.attrs["rotate"]){
          vline.rotate(element.attrs["rotate"], vlineX, vlineY)
          vline.attrs["rotate"] = element.attrs["rotate"]
        }
        set.push(vline);
      break;
      case "image":
        let image = paper.image(element.attrs["src"], element.attrs["x"], element.attrs["y"], element.attrs["width"], element.attrs["height"])
          .attr({'stroke-width':element.attrs["stroke-width"]});
        if (element.attrs["rotate"]){
          image.rotate(element.attrs["rotate"], element.attrs["x"] + element.attrs["width"] / 2, element.attrs["y"] + element.attrs["height"] / 2);
          image.attrs["rotate"] = element.attrs["rotate"]
        }
        set.push(image);
      break;
      case "text":
        let text = paper.text(element.attrs["x"], element.attrs["y"], element.attrs["text"])
          .attr({stroke: element.attrs["stroke"], "stroke-width": element.attrs["stroke-width"],
          "font-size": element.attrs["font-size"],"text-anchor": "middle", "fill": element.attrs["fill"]});
        if (element.attrs["rotate"]){
          text.rotate(element.attrs["rotate"], element.attrs["x"], element.attrs["y"]);
          text.attrs["rotate"] = element.attrs["rotate"]
        }
        set.push(text);
      break;
      case "path":
        if (element.attrs["path"].length == 2){ // 直线
          let linePath = element.attrs["path"];
          if (linePath[1][2] == linePath[0][2]){ // 横线
            element.type = "line";
          }
          else{
            element.type = "vline";
          }
        }
        else{ // 三角
          element.type = "triangle";
        }
        parseUserObj(set, [element]);
      break;
      case "set":
        set.push(parseUserObj(set, element.children));
      break;
      default:
      break;
    }
  }
}

/*
  * 定义缩放按钮
  * params:画布,缩放方向
*/
function drawScaleBtn(paper, direction){
  let outer = paper.rect(0, 0, 5, 5)
    .drag(outerMove, outerStartMove, outerEndMove)
    .attr({fill: "black"})
    .hover(function(){
      outer.attr('cursor', direction + '-resize');
    },function(){});

  let outerX = 0;
  let outerY = 0;
  let parentW = 0; // 组件宽度
  let parentH = 0; // 组件高度

  let startWidth = 1;
  let startHeight = 1;

  function outerStartMove(){
    this.mx = this.attr("x");
    this.my = this.attr("y");
    outerX = this.attr("x");
    outerY = this.attr("y");
    parentW = currentObj.getBBox().width;
    parentH = currentObj.getBBox().height;
    startWidth = currentObj.getBBox().width;
    startHeight = currentObj.getBBox().height;
  }

  function outerMove(dx, dy, x, y){
    dx = dx / 50;
    dy = dy / 50;
    objCenterX = currentObj.getBBox().x + currentObj.getBBox().width / 2 ;
    objCenterY = currentObj.getBBox().y + currentObj.getBBox().height / 2;
    parentW = currentObj.getBBox().width;
    parentH = currentObj.getBBox().height;
    let childRotate = [];
    if (currentObj.type == "set"){
      for(let i = 0; i < currentObj.length; i++){
        let elem = currentObj[i];
        childRotate[i] = elem.attrs["rotate"];
        if (childRotate[i]){
          elem.rotate(0, elem.getBBox().x + elem.getBBox().width / 2, elem.getBBox().y + elem.getBBox().height / 2);
        }
      }
    }
    switch(direction){
      case "n": // 北面
        if (dy > 0){ // 向下
          if (parentH > 0){
            currentObj.scale(1, (parentH - dy) / parentH, objCenterX, objCenterY).resetScale();
          }
        }
        else{ // 向上
          if (parentH < objMaxsize){
            currentObj.scale(1, (parentH - dy) / parentH, objCenterX, objCenterY).resetScale();
          }
        }
      break;
      case "e": // 东面
        if (dx < 0){ // 向左
          if (parentW > 0){
            currentObj.scale((parentW + dx) / parentW, 1, objCenterX, objCenterY).resetScale();
          }
        }
        else{ // 向右
          if (parentW < objMaxsize){
            currentObj.scale((parentW + dx) / parentW, 1, objCenterX, objCenterY).resetScale();
          }
        }
      break;
      case "s": // 南面
        if (dy < 0){ // 向上
          if (parentH > 0){
            currentObj.scale(1, (parentH + dy) / parentH, objCenterX, objCenterY).resetScale();
          }
        }
        else{ // 向下
          if (parentH < objMaxsize){
            currentObj.scale(1, (parentH + dy) / parentH, objCenterX, objCenterY).resetScale();
          }
        }
      break;
      case "w": // 西面
        if (dx > 0){ // 向右
          if (parentW > 0){
            currentObj.scale((parentW - dx) / parentW, 1, objCenterX, objCenterY).resetScale();
          }
        }
        else{ // 向左
          if (parentW < objMaxsize){
            currentObj.scale((parentW - dx) / parentW, 1, objCenterX, objCenterY).resetScale();
          }
        }
      break;
      case "ne": // 东北
        if (dx < 0){ // 向下左
          if (parentW > 0){
            currentObj.scale((parentW + dx) / parentW, (parentW + dx) / parentW, objCenterX, objCenterY).resetScale();
          }
        }
        else{ // 向上右
          if (parentW < objMaxsize && parentH < objMaxsize){
            currentObj.scale((parentW + dx) / parentW, (parentW + dx) / parentW, objCenterX, objCenterY).resetScale();
          }
        }
      break;
      case "nw": // 西北
        if (dx > 0){ // 向下右
          if (parentW > 0){
            currentObj.scale((parentW - dx) / parentW, (parentW - dx) / parentW, objCenterX, objCenterY).resetScale();
          }
        }
        else{ // 向上左
          if (parentW < objMaxsize && parentH < objMaxsize){
            currentObj.scale((parentW - dx) / parentW, (parentW - dx) / parentW, objCenterX, objCenterY).resetScale();
          }
        }
      break;
      case "se": // 东南
        if (dx < 0){ // 向下左
          if (parentW > 0){
            currentObj.scale((parentW + dx) / parentW, (parentW + dx) / parentW, objCenterX, objCenterY).resetScale();
          }
        }
        else{ // 向上右
          if (parentW < objMaxsize && parentH < objMaxsize){
            currentObj.scale((parentW + dx) / parentW, (parentW + dx) / parentW, objCenterX, objCenterY).resetScale();
          }
        }
      break;
      case "sw": // 西南
        if (dx > 0){ // 向上右
          if (parentW > 0){
            currentObj.scale((parentW - dx) / parentW, (parentW - dx) / parentW, objCenterX, objCenterY).resetScale();
          }
        }
        else{ // 向下左
          if (parentW < objMaxsize && parentH < objMaxsize){
            currentObj.scale((parentW - dx) / parentW, (parentW - dx) / parentW, objCenterX, objCenterY).resetScale();
          }
        }
      break;
    }
    
    if (currentObj.type == "set"){
      for(let i = 0; i < currentObj.length; i++){
        let elem = currentObj[i];
        if (childRotate[i]){
          elem.rotate(childRotate[i], elem.getBBox().x + elem.getBBox().width / 2, elem.getBBox().y + elem.getBBox().height / 2);
        }
      }
    }
    setProperty();
  }

  function outerEndMove(e){
    objCenterX = currentObj.getBBox().x + currentObj.getBBox().width / 2 ;
    objCenterY = currentObj.getBBox().y + currentObj.getBBox().height / 2;
    undos.push({ command: "ResizeObjectCommand", obj: currentObj, dWidth: currentObj.getBBox().width / startWidth, dHeight: currentObj.getBBox().height / startHeight });
    console.log(undos)
    this.animate({"fill-opacity": 1}, 300);
  }

  outer.hide();
  return outer;
}

/*
  * 定义旋转按钮
  * params:画布
*/
function drawRotateBtn(paper){
  let rotate = paper.image("/src/assets/images/rotate.svg", 0, 0, 8, 8)
    .drag(rotateMove, rotateStartMove, rotateEndMove)
    .attr({fill: "black"})
    .hover(function(){
      rotate.attr('cursor', 'move');
    },function(){});

  let rotateTemp = 0; // 组件旋转角度

  function rotateStartMove(){
    rotateTemp = currentObj.attrs["rotate"] ? currentObj.attrs["rotate"] : 0;
  }

  let ddx = 0; // 旋转结束后的角度
  function rotateMove(dx,dy,x,y){
    objCenterX = currentObj.getBBox().x + currentObj.getBBox().width / 2;
    objCenterY = currentObj.getBBox().y + currentObj.getBBox().height / 2;
    currentObj.rotate(rotateTemp + dx / 10, objCenterX, objCenterY);
    ddx = dx / 10;
    propertyForm.rotate = rotateTemp + dx / 10;
  }

  function rotateEndMove(e){
    currentObj.attrs["rotate"] = rotateTemp + ddx;
    this.animate({"fill-opacity": 1}, 300);
    undos.push({ command: "RotateObjectCommand", obj: currentObj, startRotate: rotateTemp, rotate: ddx });
  }
  rotate.hide();
  return rotate;
}

/*
  * 删除元素
*/
function deleteObj(obj){
  if (obj){
    obj.hide();
    if (currentObj == obj){
      currentObj = null;
      rotateBtn.hide();
      resizeSet.hide();
    }
    undos.push({ command: "DeleteObjectCommand", obj: obj });
  }
  else if (currentObj){
    let obj = currentObj;
    obj.hide();
    currentObj = null;
    rotateBtn.hide();
    resizeSet.hide();
    undos.push({ command: "DeleteObjectCommand", obj: obj });
  }
}

/*
  * 新增元素元素
*/
function addObj(element){
  let obj = null;
  switch (element.type){
    case "rect":
      obj = drawRect(paper, element.attrs["x"], element.attrs["y"], element.attrs["width"], element.attrs["height"], 
        element.attrs["stroke-width"], element.attrs["fill"], element.attrs["stroke"], element.attrs["rotate"]);
    break;
    case "circle":
      obj = drawCircle(paper, element.attrs["cx"], element.attrs["cy"], element.attrs["r"], 
        element.attrs["stroke-width"], element.attrs["fill"], element.attrs["stroke"]);
    break;
    case "ellipse":
      obj = drawEllipse(paper, element.attrs["cx"], element.attrs["cy"], element.attrs["rx"], element.attrs["ry"], 
        element.attrs["stroke-width"], element.attrs["fill"], element.attrs["stroke"], element.attrs["rotate"]);
    break;
    case "triangle":
      let path = element.attrs["path"];
      let width = path[2][1] - path[0][1];
      let height = path[0][2] - path[1][2];
      let x = path[0][1] + width / 2;
      let y = path[0][2] - height / 2;
      obj = drawTriangle(paper, x, y, width, height, element.attrs["stroke-width"], element.attrs["fill"], 
        element.attrs["stroke"], element.attrs["rotate"]);
    break;
    case "line":
      let linePath = element.attrs["path"];
      let lineWidth = linePath[1][1] - linePath[0][1];
      let lineX = linePath[0][1] + lineWidth / 2;
      let lineY = linePath[0][2];
      obj = drawLine(paper, lineX, lineY, lineWidth, element.attrs["stroke-width"], element.attrs["stroke"], 
        element.attrs["rotate"]);
    break;
    case "vline":
      let vlinePath = element.attrs["path"];
      let vlineheight = vlinePath[1][2] - vlinePath[0][2];
      let vlineX = vlinePath[0][1];
      let vlineY = vlinePath[0][2] + vlineheight / 2;
      obj = drawVerticalLine(paper, vlineX, vlineY, vlineheight, element.attrs["stroke-width"], element.attrs["stroke"], 
        element.attrs["rotate"]);
    break;
    case "image":
      obj = drawImage(paper, element.attrs["x"], element.attrs["y"], element.attrs["src"], element.attrs["width"], 
        element.attrs["height"], element.attrs["stroke-width"], element.attrs["rotate"]);
    break;
    case "text":
      obj = drawText(paper, element.attrs["x"], element.attrs["y"], element.attrs["text"], element.attrs["font-size"], 
        element.attrs["stroke-width"], element.attrs["fill"], element.attrs["stroke"], element.attrs["rotate"],
        element.attrs["dataSource"], element.attrs["column"]);
    break;
    case "set":
      obj = drawUserObj(element.children);
    break;
    default:
    break;
  }
  mainArr.push(obj);
  return obj;
}

/*
  * 清空画布
*/
function clear(){
  ElMessageBox.confirm("确认清空画布?", "警告", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
  }).then(
    () => {
      for(let i = 0; i < mainArr.length; i++){
        let elem = mainArr[i];
        elem.remove();
      }
      mainArr = [];
      currentObj = null;
      rotateBtn.hide();
      resizeSet.hide();
    },
    () => {
    }
  );
}

const saveDialogVisible = ref(false);

/*
  * 置底
*/
function toBack(){ 
  if (currentObj){
    currentObj.toBack();
    mainArr = mainArr.filter(item => item != currentObj);
    mainArr.push(currentObj);
  }
}

/*
  * 置顶
*/
function toFront(){ 
  if (currentObj){
    currentObj.toFront();
    mainArr = mainArr.filter(item => item != currentObj);
    mainArr.unshift(currentObj);
  }
}

/*
  * 保存
*/
function saveDiagram(){ 
  resizeSet.hide();
  rotateBtn.hide();
  let elements = parseSet(mainArr);
  if (elements.length == 0){
    ElMessage.error("画布为空");
    return false;
  }
  let svgElement = document.getElementById('paper');
  svgToImage(svgElement, svgElement.clientWidth, svgElement.clientHeight, function(dataURL){
    diagramForm.elements = JSON.stringify(elements);
    diagramForm.img = dataURL;
    if (route.query.id) {
      diagramForm.id = route.query.id
      DesdiagramAPI.update(diagramForm).then(() => {
        ElMessage.success("修改成功");
        saveDialogVisible.value = false;
      });
    } else {
      DesdiagramAPI.create(diagramForm).then(() => {
        ElMessage.success("新增成功");
        saveDialogVisible.value = false;
      });
    }
  });
}

/*
  * 解析组件集
*/
function parseSet(set){ 
  let elements = [];
  for(let i = 0; i < set.length; i++){
    let elem = set[i];
    if (elem.removed == true) continue;
    if (elem.type == "path"){
      if (elem.attrs.path.length == 2){ // 直线
        let linePath = elem.attrs.path;
        if (linePath[1][2] == linePath[0][2]){ // 横线
          elements.push({
            type: "line",
            attrs: elem.attrs,
          })
        }
        else{ // 竖线
          elements.push({
            type: "vline",
            attrs: elem.attrs,
          })
        }
      }
      else { // 三角
        elements.push({
          type: "triangle",
          attrs: elem.attrs,
        })
      }
    }
    else if (elem.type == "set"){
      let x = elem.getBBox().x + elem.getBBox().width / 2 ;
      let y = elem.getBBox().y + elem.getBBox().height / 2;
      elements.push({
        type: "set",
        attrs: { "x": x, "y": y },
        children: parseSet(elem),
      })
    }
    else{
      elements.push({
        type: elem.type,
        attrs: elem.attrs,
      })
    }
  }
  return elements;
}

/*
  * 导出png图片
*/
function exportPng(){ 
  resizeSet.hide();
  rotateBtn.hide();
  let svgElement = document.getElementById('paper');
  svgToImage(svgElement, svgElement.clientWidth, svgElement.clientHeight, function(dataURL){
    // 此处的dataURL就是转换后的图片的DataURL
    // 你可以使用这个dataURL做进一步的操作，比如下载或者显示图片
    var a = document.createElement('a');
    a.href = dataURL;
    a.download = 'image.png';
    a.click();
  })
}

/*
  * svg转图片
*/
function svgToImage(svgElement, width, height, callback) {
    // 创建一个Canvas对象
    var canvas = document.createElement('canvas');
    canvas.width = width;
    canvas.height = height;
 
    // 绘制Canvas
    var ctx = canvas.getContext('2d');
    var data = (new XMLSerializer()).serializeToString(svgElement);
    var DOMURL = window.URL || window.webkitURL || window;
    var img = new Image();
    var svgBlob = new Blob([data], {type: 'image/svg+xml;charset=utf-8'});
    var url = DOMURL.createObjectURL(svgBlob);
 
    img.onload = function() {
        ctx.drawImage(img, 0, 0);
        DOMURL.revokeObjectURL(url);
        callback(canvas.toDataURL('image/png')); // 输出图片的DataURL
    };
 
    img.src = url;
}

/*
  * 导出svg
*/
function exportSvg(){ 
  resizeSet.hide();
  rotateBtn.hide();
  // 创建Blob对象
  var serializer = new XMLSerializer();
  var svgString = serializer.serializeToString(paper.canvas);
  var blob = new Blob([svgString], {type: 'image/svg+xml;charset=utf-8'});
  var url = URL.createObjectURL(blob);
  
  // 创建下载链接
  var a = document.createElement('a');
  a.href = url;
  a.download = 'canvas.svg';
  a.click();
}

const activeIcon = ref("ArrowLeftBold");
function showPropertyDiv()  {
  if (showProperty.value){
    showProperty.value = false;
    activeIcon.value = "ArrowLeftBold";
  }
  else{
    showProperty.value = true;
    activeIcon.value = "ArrowRightBold";
  }
}

</script>

<style scoped>
  .mainDiv {
    width: 100%;
    min-height: calc(100vh - 60px);
  }
  .componentDiv {
    width: 200px;
    height: calc(100vh - 60px);
    float: left;
    overflow: auto;
  }
  .diagramDiv {
    width: calc(100% - 200px);
    min-height: calc(100vh - 60px);
    float: left;
  }
  .property {
    width: 250px;
    background-color: white;
    position: absolute;
    top: 10px;
    right: 10px;
  }
  .slide {
    width: 24px;
    height: 24px;
    position: absolute;
    top: 300px;
    right: 20px;
  }
  .slide-btn {
    width: 24px;
    height: 24px;
  }
  .btnDiv {
    position: absolute;
    top: 10px;
    left: 200px;
  }
  .image-select .image {
    width: 32px;
    height: 32px;
    display: block;
  }
  .image-select .el-upload {
    border: 1px dashed var(--el-border-color);
    border-radius: 6px;
    cursor: pointer;
    position: relative;
    overflow: hidden;
    transition: var(--el-transition-duration-fast);
  }
  
  .image-select .el-upload:hover {
    border-color: var(--el-color-primary);
  }
  
  .el-icon.image-select-icon {
    font-size: 28px;
    color: #8c939d;
    width: 32px;
    height: 32px;
    text-align: center;
  }
</style>
